home *** CD-ROM | disk | FTP | other *** search
- %% Notas para la creaci
- n del fichero .dvi de impresi
- %% He intentado eliminar todas las dependencias con ficheros de formato
- %% de TeX que he podido para que se pueda pasar por plain TeX.
- %% Utiliza el comando 'itex E_spanish.tex'
- %% donde itex es 'virtex &iplain', y iplain se cre
- utilizando:
- %%----inicio fichero
- %%\input plain
- %%\input amiga
- %%\def\fmtname{iplain}
- %%\dump
- %%----fin fichero
- amiga.tex lo puedes encontrar al final del fichero!!!
- %% Las
- nicas dependencias que quedan son las dos primeras l
- neas:
- %%\selectlanguage{spanish}
- %% que es necesaria para que TeX incluya el guionado de forma correcta
- %% esto forma parte del paquete 'babel'. Puedes eliminar esta l
- %% con lo que es probable que TeX utilice guionado ingles, y puede que
- %% necesites indicar el punto de ruptura de algunas palabras con '\-'.
- %%\input manmac
- %% manmac.tex deber
- a incluirse en tu distribuci
- n de TeX, si no,
- %% contacta conmigo, y yo te puedo enviar una versi
- n de ese fichero.
- %% u0868551@oboe.etsiig.uniovi.es
- % Este manual tiene copyright (C) 1995 de Antonio J. Gomez Gonzalez.
- % !`Reservados todos los derechos!
- \selectlanguage{spanish}
- \input manmac
- %% Mis macros para este libro
- \hsize=32pc \vsize=52pc
- \hoffset=1.52cm %3.57pc
- \pagewidth=32pc \pageheight=52pc
- \parindent=2em
- \catcode`@=11 % borrow the private macros of PLAIN (with care)
- %% Si quieres obtener unas marcas para ver si las paginas quedan centradas,
- %% comenta la siguiente linea (con %).
- \def\setcornerrules{}
- \outer\def\subsec#1. {\medbreak\advance\subsecno by 1
- \noindent{\it \the\subsecno.\enspace#1.\enspace}}
- \outer\def\adver'#1'#2'#3'{\d@nger {\bf #1}\hfil\break #3\hfil\break}
- \outer\def\error'#1'#2'#3'{\dd@nger {\bf #1}\hfil\break #3\hfil\break}
- \catcode`\@=\other
- \def\fadver{\endgraf\endgroup} % omits the \medbreak
- \def\ferror{\endgraf\endgroup} % omits the \medbreak
- \let\centrada=\centerline
- \let\derecha=\rightline
- \let\izquierda=\leftline
- \def\b/{/\penalty\exhyphenpenalty} % una `/' que actua como un `-'
- %% nueva macro para notas a pie de pagina numeradas de forma automatica.
- \newcount\numeronota
- \def\reinicianotas{\numeronota=0\relax}
- \def\nota{\advance\numeronota by 1
- \footnote{$^{\the\numeronota}$}}
- %% fin nueva macro
- \outer\def\seccion#1. {\bigbreak
- \subsecno=0
- \noindent{\docess #1.\par\nobreak\smallskip\nobreak}\noindent}
- %% Yo prefiero los contenidos en tipo slanted
- \def\<#1>{\leavevmode\hbox{$\langle${\sl #1}\/$\rangle$}} % syntactic quantity
- \def\acerca{\stretch}
- \def\noin{\noindent}
- \def\bloque{\bull}
- \def\finpar{\parbreak}
- \def\lineas{\beginlines}
- \def\finlineas{\endlines}
- \def\finlineasligero{\weakendlines}
- \def\finlineasfinal{\finalendlines}
- \font\docess=cmss12
- \def\pregunta#1{\Espacio\item{$-$} {\sl #1}\par\nobreak\smallskip\nobreak}
- \def\ejemplos{\par\nobreak\vbox\bgroup\halign\bgroup ##\hfil&\qquad##\hfil\cr}
- \def\Ejemplos{\smallskip \vbox\bgroup\halign\bgroup ##\hfil&\qquad##\hfil\cr}
- \def\fin{\egroup\egroup\noindent\ignorespaces}
- \def\finsma{\egroup\egroup\smallskip\noindent\ignorespaces}
- \def\finmed{\egroup\egroup\smallskip\noindent\ignorespaces}
- \def\proto#1{\medskip\noindent\quad{\tt #1}\par\nobreak\smallskip\nobreak\noindent\ignorespaces}
- \def\pproto#1{\vskip-\smallskipamount\noindent\quad{\tt #1}\par\nobreak\smallskip\nobreak\noindent\ignorespaces}
- \def\espacio{\smallskip\noindent\ignorespaces}
- \def\Espacio{\medskip\noindent\ignorespaces}
- \def\Esptab{\noalign{\medskip}}
- \def\esptab{\noalign{\smallskip}}
- \def\bartab{\noalign{\smallskip\hrule\smallskip}}
- \def\E/{Amiga~E}
- \def\ASCII/{{\sc ASCII}}
- \def\saltacap{\eject\reinicianotas}
- \titlepage
- \pageno=-1995
- \line{\cmman \hfill E\hfill}
- \vfill
- \line{\sl\hfill Por Antonio J. Gomez Gonzalez\hfill}
- \line{\sl\hfill u0868551@oboe.etsiig.uniovi.es\hfill}
- \eject
- % title
- \pageno=-1 % the front matter is numbered with roman numerals
- \font\auth=cmssdc10 scaled\magstep4 % used only on the title page
- \font\elevenbf=cmbx10 scaled\magstephalf % ditto
- \font\elevenit=cmti10 scaled\magstephalf % ditto
- \font\elevenrm=cmr10 scaled\magstephalf % ditto
- \titlepage
- \line{\cmman \hfill E\hfill}
- \vskip 1pc
- \baselineskip 13pt \elevenbf
- \halign to\hsize{#\hfil\tabskip 0pt plus 1fil\hfil\tabskip0pt\cr
- \kern5.5mm\auth Wouter \kern-1ptvan \kern-1ptOortmerssen&\cr
- \noalign{\vskip 12pc}
- &\elevenit Traducido por\cr
- &Antonio J. \kern-1ptGomez Glez\cr
- \noalign{\vfill}
- &Gij\'on\enspace$\cdot$\enspace Espa\~na\cr}
- \eject
- % copyright
- \titlepage
- \eightpoint
- \vbox to 8pc{}
- \noindent\strut
- Este manual describe la versi\'on 3.1a del compilador de \E/\null{}. Algunas
- de las caracter\'{\i}sticas avanzadas que se describen aqu\'{\i} no est\'an
- presentes en versiones anteriores.
- \Espacio
- Este texto est\'a dise\~nado para ser impreso, y difiere en ciertos aspectos
- de la gu\'{\i}a de |amigaguide| del compilador, aunque en muy pocos
- aspectos.
- \Espacio
- \E/ tiene copyright $\copyright$ de Wouter van Oortmerssen.
- \vfill
- \noindent
- {\sl \kern-1pt Segunda impresi\'on, revisada, Abril 1995} % hardcover
- \espacio
- Copyright $\copyright$ 1995 por Antonio Joqu\'{\i}n Gomez Gonzalez
- \espacio
- Este libro se publica como parte de la distribuci\'on de la versi\'on v3.1a
- de \E/\null{}. Debe quedar claro que el \'unico responsable de la fiabilidad
- de esta traducci\'on es Antonio J.~Gomez Gonzalez, aunque por otra
- parte, no acepto ninguna responsabilidad sobre da\~nos provocados por su
- lectura, es decir, ac\'eptala como es.
- \Espacio
- ISBN 0-000-00000-0\par % paperback
- \eject
- \reinicianotas
- % the preface
- \titlepage
- \def\rhead{Introducci\'on}
- \vbox to 8pc{
- \derecha{\titlefont Introducci\'on}\vss}
- {\topskip 9pc % this makes equal sinkage throughout the Preface
- \vskip-\parskip
- \tenpoint
- \noindent\hang\hangafter-2
- \smash{\lower12pt\hbox to 0pt{\hskip-\hangindent\cmman G\hfill}}\hskip-4pt
- {\sc ENEROSO} L{\sc ECTOR}: \strut Este es un libro sobre \E/\null{}, el cual
- es un lenguaje de alto nivel orientado a objetos\b/procedural\b/funcional no puro,
- influenciado en gran medida por lenguajes tales como C++,
- Ada, Lisp, etc. Es un lenguaje de programaci\'on de prop\'osito general, y
- la implementaci\'on para Amiga est\'a dirigida espec\'{\i}ficamente a programar
- aplicaciones de sistema. El n\'umero de caracter\'{\i}sticas del lenguaje es
- demasiado grande como para resumirlas todas, entre las cuales se incluye:
- velocidad de compilaci\'on superior a~20000 l\'{\i}neas por minuto en un Amiga
- a~7~Mhz, ensamblador en l\'{\i}nea y enlazador\nota{linker.} integrados dentro del
- compilador, un gran conjunto de funciones integradas, buen concepto de
- m\'odulos con includes de v39 como m\'odulos, sistema de tipos flexible,
- expresiones {\it entrecomilladas}, listas inmediatas, con tipo, polimorfismo
- a bajo nivel y de objetos, manejo de excepciones, herencia, ocultamiento
- de datos, m\'etodos, valores de retorno m\'ultiples, argumentos por omisi\'on,
- reserva de registros, manejo r\'apido de memoria, unificaci\'on, \hbox{Celdas-LISP},
- (macro-)preprocesador, depurador a nivel de fuente, y mucho m\'as~\dots
- \Espacio
- Veamos nuestro primer programa en E, el {\tt HolaMundo} de siempre:
- \begintt
- /* nominado para ejemplo `mas aburrido' */
- PROC main()
- WriteF('!`Hola Mundo!\n')
- ENDPROC
- \endtt
- \noin La distribuci\'on incluye:
- \vbox{\settabs\+\indent&modules\qquad&\cr
- \+&bin/& compilador |EC| y las utilidades de apoyo.\cr
- \+&modules/& m\'odulos E de Amiga v39 y utilidades en m\'odulos enlazables.\cr
- \+&docs/& documentaci\'on de E.\cr
- \+&src/& fuentes de ejemplo en E.\cr
- \+&tools/& herramientas opcionales para usar con E.\cr
- \noin La distribuci\'on de \E/ v3.0 que incluye la versi\'on de demostraci\'on del
- compilador es FreeWare y se puede copiar libremente. Algunos de vosotros habreis
- recibido un archivo con la versi\'on registrada del compilador, el cual {\bf NO} es
- FreeWare, y {\bf NADIE} m\'as debe copiarlo.
- No est\'a autorizada la distribuci\'on de \E/ por un importe superior al de
- disco+correo (menos de 500~pts), as\'{\i} como tampoco se autoriza ning\'un otro tipo de
- distribuci\'on cuyo \'unico prop\'osito sea el de obtener beneficios.
- {\bf Prohibo} a Serge Hamouche o su compa\~nia {\sl France Festival Distribution}
- distribuir E de forma alguna\nota{Serge Hamouche ha distribuido~E sin mi permiso,
- utilizando mi nombre de forma incorrecta y rob\'andome dinero a expensas de los
- programadores de~E franceses. Si le has pagado dinero, recl\'amaselo y com\'enta esta
- situaci\'on a toda la gente que puedas para que no lo sigua haciendo.}. Por otro
- lado, hay una traducci\'on de este documento en franc\'es con mi autorizaci\'on
- (realizada por Olivier~Anh) que est\'a disponible en Aminet.
- Esta distribuci\'on debe ofrecerse siempre como un todo, es decir, de la misma
- forma que el archivo |.lha| original. Sin a\~nadidos, modificaciones, traducciones,
- distribuciones parciales o cualquier otra cosa que se pueda hacer sin mi permiso.
- No hay garant\'{\i}as. Si consigues ahogar al pez que tienes en la pecera usando~E, o
- si~E resulta no ser apropiado para pedir pizzas, ese es t\'u problema (y s\'olo tuyo).
- Pase lo que pase no me maldigas por ello.
- \medskip
- Fred Fish tiene premiso especial para distribuir~E en sus \hbox{CD-ROMs}.
- \medskip
- La distribuci\'on de \E/ es PD\null{}, y contiene la versi\'on demo del compilador.
- Los programadores registrados obtienen el compilador completo en un archivo a
- parte, en el que s\'olo est\'a |EC|.
- As\'{\i} que, ?`que hay de la versi\'on demo que se incluye? El compilador s\'olo crear\'a
- ejecutables de menos de 8KB, por encima de esos 8KB mostrar\'a el error
- |"workspace full"|\nota{espacio de trabajo lleno.} A parte de eso, es totalmente
- funcional. Puedes evaluar la demo durante {\bf dos semanas}, tras las cuales debes
- decidir si registrarte o dejar de usarla, incluso si s\'olo escribes programas de
- menos de 8KB\nota{Sol\'{\i}an ser 12KB, s\'{\i}, !`adivina porqu\'e lo cambi\'e!}.
- Para ver el coste de una copia, la forma de enviar el dinero, donde enviarlo,~\dots
- echa un vistazo a lo documentaci\'on electr\'onica de la distribuci\'on. Aseg\'urate
- de enviar informaci\'on tan completa como puedas con el dinero, por ejemplo,
- direcci\'on completa, direcci\'on de correo electr\'onico, incluso puedes a\~nadir la
- configuraci\'on de tu Amiga. Yo no voy a escribir aqu\'{\i} uno de esos tontos impresos
- de registro |:-)|
- Las actualizaciones de la distribuci\'on se pueden encontrar en DP como siempre, y
- las actualizaciones del EC registrado se distribuyen como parches, tambi\'en en
- Dom\'{\i}nio P\'ublico.
- Si ya has recibido el EC registrado, ser\'{\i}a conveniente que lo pusieras en el
- directorio |bin/|. Todo el mundo puede copiar libremente el archivo de
- distribuci\'on, pero, por favor, aseg\'urate de que no distribuyes tu copia registrada
- de EC a nadie, ni siquiera a los amigos. No he serializado esas copias por la
- confianza que tengo en mis usuarios registrados, por ello, no rompas esa confianza.
- La cuota de registro es bastante asequible, y la versi\'on v2.1b sigue estando
- disponible, por lo que no hay excusa para que piratees~E.
- El compilador de \E/ ha sido desarrollado a lo largo de m\'as de tres~a\~nos
- y~medio, fruto de las ideas del autor sobre un buen lenguaje de programaci\'on, y un
- compilador de calidad espec\'{\i}fico del Amiga. Ha sido programado (como podr\'as haber
- apreciado) 100\% en ensamblador, usando el ensamblador AsmOne~v1.02. Todos los
- dem\'as programas de apoyo han sido programados en el propio \E/.
- \Espacio
- Agradezco especialmente a la siguiente gente:
- \vbox{\settabs\+\qquad&Jason Hualance\quad&\cr
- \+&Barry Wills& $-$ por ser el mejor mejor betatester de siempre.\cr
- \+&Jason Hulance& $-$ por su trabajo en {\sl The Beginners Guide}, y betatest.\cr
- \+&Rob Verver& $-$ por comentarios/inspiraci\'on.\cr
- \noin Tambi\'en me gustar\'{\i}a agredecer a los siguientes por varias razones (sin un
- orden particular) :
- \midinsert\narrower
- \noin Raymond Hoving, Erwin van~Breemen, Michael Zuchhi, James Cooper, Jens
- Gelhar, Paolo Silvera, Sergio Ruocco, Jeroen Vermeulen, Jan van den
- Baard, Joerg Wach, Norman Kraft, Urban Mueller, Charles McCreary, Olivier
- Anh, Lionel Vintenat, Rob Nottage, and many more~\dots
- \endinsert
- Este compilador se ha programado poniendo mucho cuidado en lo referente a
- fiabilidad, y m\'as cuidado a\'un en el c\'odigo que genera, adem\'as ha sido comprobado y
- depurado durante largo tiempo. Sin embargo, es muy posible que contenga alg\'un
- error. Si llegas a encontrar uno, o tienes otros comentarios\b/preguntas,
- escr\'{\i}beme a la direcci\'on de m\'as abajo: Prefiero {\bf con diferencia} correo
- electr\'onico sobre correo convencional.
- {\bf Apunta bien}: debido a la gran popularidad de las versiones anteriores de
- \E/, recibo una cantidad casi incontestable de correo electr\'onico, buena parte
- del cual (|>90%|) son preguntas que no ser\'{\i}an necesarias si la gente leyera los
- documentos con cuidado. Lo que quiero decir es que me gusta recibir correo
- electr\'onico, y no me importa responder preguntas y ayudar a la gente con problemas
- de programaci\'on, pero, antes de escribirme, aseg\'urate de comprobar los documentos
- que tienes a tu disposici\'on (como los documentos de \E/ o los RKRMs) para ver si la
- pregunta es relevante. M\'as precismente, no debeis enviarme preguntas que no son
- espec\'{\i}ficas de E, sino del Amiga. E~intenta ser amable conmigo con comentarios
- como ``{\sl Yo creo que \E/ debe tener la caracter\'{\i}stica X\/}~\dots ''\nota{N.T.:
- por supuesto en ingl\'es $;-)$}. Hecha un vistazo a la FAQ.
- \Espacio
- Ser\'an bien recibidos registros y donaciones en la siguiente direcci\'on:
- \vbox{\settabs\+\indent\qquad&\cr
- \+&Wouter van Oortmerssen\cr
- \+&Levendaal 87\cr
- \+&2311 JG Leiden\cr
- \+&HOLANDA\cr
- \noin o, mejor, si tienes acceso a correo electr\'onico:
- \vbox{\settabs\+\indent\qquad&\cr
- \+&wouter@mars.let.uva.nl\cr
- \+&wouter@alf.let.uva.nl\qquad (si mars rebota)\cr
- \bigskip
- \line{{\sl Gij\'on, Asturias}\hfil--- A. J. G. G.}
- \line{\sl Marzo 1995\hfil}
- } % end of the special \topskip
- \endchapter\saltacap
- \beginchapter Cap\'{\i}tulo 1. Usando el\\compilador
- \pageno=1 % Pagina numero 1
- Para instalar \E/ en tu sistema, s\'olo tienes que copiar toda la distribuci\'on en
- alg\'un lugar de tu sistema, extender tu path al directorio |BIN|, \thinspace y
- asignar |EModules:| \negthinspace al directorio |MODULES|.
- \espacio
- Sintaxis del compilador (2.04+):
- \begintt
- SOURCE/A,REG=NUMREGALLOC/N/K,LARGE/S,SYM=SYMBOLHUNK/S,NOWARN/S,
- QUIET/S,ASM/S,ERRLINE/S,ERRBYTE/S,SHOWBUF/S,ADDBUF/N/K,
- IGNORECACHE/S,HOLD/S,WB/S,LINEDEBUG/S,OPTI/S,DEBUG/S:
- \endtt
- Sintaxis para 1.2 a 2.03:
- \begintt
- EC [-opcs] <fichero_fuente>
- \endtt
- Puedes ver las opciones estandard de AmigaDos en cualquier momento
- escribiendo `|EC ?|'. Las opciones en las versiones \hbox{1.2$-$2.03} del sistema
- son de tipo Unix (hay que escribirlas todas juntas, precedidas de ``$-$''). La mayor
- parte de las veces no necesitar\'as usar estas opciones. Veamos su significado:
- \smallskip
- \vbox{\halign{{\tt#}\hfil&\enspace{\tt#}\hfil&
- \enspace\vtop{\parindent=0pt\hsize=24pc\hangindent=0pt\strut#\strut}\cr
- 2.04+&1.2+&Descripci\'on\cr
- \bartab
- LARGE& -l& Compila con modelo c\'odigo/datos grande. \hfill|OPT LARGE|\cr
- ASM& -a& Pasa |EC| a modo ensamblador.\hfill|OPT ASM|\cr
- NOWARN& -n& Suprime advertencias.\hfill|OPT NOWARN|\cr
- SYM& -s& Inserta un |symbolhunk| al ejecutable, que utilizar\'an
- los profilers, depuradores, desensambladores~\dots\cr
- LINEDEBUG& -L& Inserta bloque de depuraci\'on |LINE| al ejecutable,
- para profilers, depuradores,~\dots \hfill|OPT LINEDEBUG|\cr
- REG=N& -rN& Hace que se reserven |N| registros por |PROC|\null{}. (0~por
- omisi\'on, !`mira en alg\'un otro sitio sobre esto!)\cr
- QUIET& -q& Pone |EC| en modo silencioso, s\'olo escribe cuando hay\
- errores o advertencias.\cr
- WB& -w& Pone el WB delante (para scripts).\cr
- SHOWBUF& -b& Muestra informaci\'on de uso de memoria de buffer.\cr
- ADDBUF=X& -mX& Hace que |EC| reserve m\'as memoria para buffers. |X| est\'a
- en el intervalo 1--9 ---n\'umero de m\'{\i}nimo de bloques
- de 100KB reservados. (1~por omisi\'on, casi no se usa)\cr
- ERRLINE& -e& |EC| retorna el n\'umero de l\'{\i}nea del error.\cr
- ERRBYTE& -E& |EC| retorna la posici\'on (en bytes) respecto al inicio
- del fichero en la que se produjo el error.\cr
- IGNORECACHE& -c& Deshabilita el uso del cach\'e de m\'odulos.\cr
- HOLD& -h& Espera a que se pulse \<|return|> antes de continuar.\cr
- OPTI& & Activa las optimizaciones (de momento es |REG=5|).\cr
- DEBUG& & Inserta informaci\'on de depuraci\'on en ejecutable o m\'odulo.\cr
- \espacio
- Por ejemplo, |ec LARGE blabla| compila |blabla.e| con modelo grande.
- \medskip
- El compilador no se puede hacer residente. Si un programa usa ficheros
- m\'odulo para definiciones de biblioteca como:
- \ejemplos
- &|MODULE 'GadTools', 'Reqtools'|\cr
- el compilador necesita saber donde est\'an. Hay dos posibles soluciones:\par
- 1. Realizar la asignaci\'on \hbox{|EModules:|} al directorio de m\'odulos (mejor).\par
- 2. Indicar en el c\'odigo fuente donde debe buscar los m\'odulos, como:
- \ejemplos
- &|OPT DIR='dh0:src/e/modules'|\cr
- \medskip
- Veamos como ejemplo la compilaci\'on del programa |HolaMundo.e|. El compilador producir\'a
- un ejecutable |HolaMundo|.
- \begintt
- E:> ec holamundo
- Amiga
- Compiler/Assembler/Linker
- v2.4f
- 91/92/93
- lexical analysing ...
- parsing and compiling ...
- no errors
- E:> holamundo
- !`Hola Mundo!
- E:> list
- HolaMundo.e 89 ----rwed Hoy 17:37:00
- HolaMundo 656 ----rwed Hoy 17:37:00
- 2 files - 4 blocks used
- \endtt
- \endchapter\saltacap
- \beginchapter Cap\'{\i}tulo 2. Formato del\\lenguaje
- \subsec Tabuladores, cambio de l\'{\i}nea, etc.
- El c\'odigo fuente en~E son ficheros en formato \ASCII/ puro, con cambio de l\'{\i}nea
- \<|lf|> y punto y coma |;| como separadores de dos sentencias. Las sentencias que
- tengan un n\'umero particularmente grande de elementos se pueden repartir a lo largo
- de varias l\'{\i}neas finaliz\'andolas con una coma (o con cualquier otro elemento l\'exico
- que normalmente no puede aparecer en el fin de l\'{\i}nea), ignorando de esa forma el
- siguiente \<|lf|>.
- \noin En un fichero de c\'odigo fuente los elementos l\'exicos pueden estar separados
- entre s\'{\i} por cualquier n\'umero de espacios, tabuladores,~\dots
- \subsec Comentarios.
- En un fichero fuente los comentarios se pueden poner en cualquier lugar en
- el que normalmente un espacio ser\'{\i}a correcto. Empiezan con |/*| y finalizan
- con |*/|, y se pueden anidar infinitamente. Lo mismo se puede decir para
- los comentarios de una l\'{\i}nea, los cuales empiezan con un |->| y finalizan en
- el primer \<|lf|>.
- \begintt
- /* esto es un comentario */
- -> esto tambi\'en.
- \endtt
- \subsec Identificadores y tipos.
- Los identificadores son cadenas que el programador usa para denotar un
- cierto objeto, en la mayor\'{\i}a de los casos variables, o incluso palabras
- claves o nombres de funciones predefinidas por el compilador. Un
- identificador est\'a formado por:
- {\obeylines
- $-$ caracteres en may\'uscula o min\'uscula.
- $-$ |0...9| (excepto como primer caracter).
- $-$ |_| (el subrayado).
- \espacio
- Todos los caracteres son significativos, aunque el compilador s\'olo
- mira los dos primeros para determinar el tipo de identificador con el que
- est\'a tratando:
- \Ejemplos
- \qquad Ambos en may\'uscula:&palabra clave como |IF|, |PROC|,~\dots\cr
- &constante, como |MAX_LENGTH|,~\dots\cr
- &mnemot\'ecinico ensamblador, como |MOVE|,~\dots\cr
- \qquad Primera min\'uscula &identificador de variable/etiqueta/objeto,~\dots\cr
- \qquad Primera may\'us.\ y seg.\ min\'us.&funci\'on del sistema E como: |WriteF()|,~\dots\cr
- &llamada de librer\'{\i}a: |OpenWindow()|,~\dots\cr
- Todos los identificadores verifican esta sintaxis, por
- ejemplo: |WBenchToFront()| se convierte en |WbenchToFront()|.
- \Espacio
- A nivel sem\'antico, los programas en~E estan formados por expresiones. Una
- expresi\'on es un fragmento de c\'odigo formado por operadores, funciones y
- par\'entesis que conforman un valor. La mayor\'{\i}a est\'an formadas por:
- {\obeylines
- $-$ valores inmediatos.
- $-$ operadores (Matem\'aticos,~\dots)
- $-$ llamadas a funciones.
- $-$ par\'entesis |()| ---determinando precedencia y agrupamiento.
- $-$ variables o expresiones variables.
- \Ejemplos
- Ejemplos de expresiones:&|1 'hola'|\cr
- &|$ABCD+(2*6)+Abs(a) (a<1) OR (b>=100)|\cr
- \finsma
- Veamos algunos de estos elementos:
- \subsec Precedencia y agrupamiento.
- El lenguaje E no tiene ning\'un tipo de precedencia. Esto quiere decir que
- las expresiones se eval\'uan de izquierda a derecha. Puedes cambiar la
- precedencia encerrando entre par\'entesis algunas (sub-)expresiones.
- \Ejemplos
- Ejemplos:&|1+2*3 /* =9 */ 1+(2*3) /* =7 */ 2*3+1 /* =7 */|\cr
- \subsec Expresiones.
- Hay tres tipos de expresiones, y se pueden usar con diferentes prop\'ositos:
- \item{$-$} \<var>, formada simplemente por una variable.
- \item{$-$} \<expvar>, formada por una variable, posiblemente con operadores
- unarios como ``|++|'' (incremento), ``|.|'' (selecci\'on de
- miembro) o ``|[]|'' (operador de arreglo). Denota una expresi\'on
- modificable (como los valores-i\nota{l-values.} del~C). Se\~nalar
- que esos operadores (unarios) no forman parte de ninguna
- precedencia.
- \item{$-$} \<exp>. Incluye \<var> y \<expvar>, y cualquier otra expresi\'on.
- \subsec Llamadas a funciones.
- La llamada a una funci\'on es una suspensi\'on temporal del c\'odigo actual
- para {\it saltar} a esa funci\'on, \'esta puede ser una funci\'on escrita por uno
- mismo (|PROC|), o una funci\'on proporcionada por el sistema. El formato de
- una llamada a funci\'on es, el nombre de la funci\'on seguido de dos par\'entesis
- que encierran argumentos que pueden ser desde~0 hasta un n\'umero ilimitado de
- ellos, que van separados por comas ``|,|''. Se\~nalar que los argumentos de
- funciones son expresiones de nuevo.
- \Ejemplos
- Ejemplos:&|foo( 1, 2 )|\cr
- &|Gadget( buffer, glist, 2, 0, 40, 80+offset, 100, 'Cancela' )|\cr
- &|Close( handle )|\cr
- \finsma
- Tanto los valores inmediatos como los operadores se detallan en los
- pr\'oximos cap\'{\i}tulos.
- \endchapter\saltacap
- \beginchapter Cap\'{\i}tulo 3. Valores\\inmediatos
- Todos los valores inmediatos en~E se eval\'uan a un resultado de 32~bits, la
- \'unica diferencia entre todos ellos puede ser su representaci\'on interna, o el
- hecho de que retornen un puntero en vez de un valor.
- \subsec Decimal (|1|\/).
- Un valor decimal es una sequencia de caracteres |0...9|, posiblemente
- precedidos de un signo menos ``|-|'' (denotando un valor negativo).
- \Ejemplos
- Ejemplos:&|1, 100, -12, 1024|\cr
- \subsec Hexadecimal (|\$1|\/).
- Un valor hexadecimal usa adem\'as los caracteres |A...F| (o |a...f|) y
- van precedidos por el caracter |$|.
- \Ejemplos
- Ejemplos:&|$FC, $DFF180, -$ABCD|\cr
- \subsec Binario (|\%1|\/).
- Los n\'umeros binarios empiezan con un caracter |%| y s\'olo usan los caracteres
- |1| y |0| para formar un valor.
- \Ejemplos
- Ejemplos:&|%111, %1010100001, -%10101|\cr
- \subsec Real (|1.0|\/).
- Los n\'umeros reales difieren de los decimales en que tienen un ``|.|'' para
- separar sus dos partes. Se puede prescindir de cualquiera de las partes,
- pero nunca las dos. Se\~nalar que la representaci\'on interna de los n\'umeros
- reales es diferente (32 bits {\sc IEEE}).
- \Ejemplos
- Ejemplos:&|3.14159, .1 (=0.1), 1. (=1.0)|\cr
- \subsec Caracter (|"a"|\/).
- El valor de un caracter (entre comillas |""|) es su valor \ASCII/, con esto
- tenemos que |"A" = 65|. En~E los valores caracter inmediatos forman una
- peque\~na cadena de hasta cuatro caracteres, por ejemplo |"FORM"|, en la que
- el primer caracter (|"F"|) es el MSB (Byte M\'as Significativo) de la
- representaci\'on de 32~bits, y |"M"| es el LSB (Byte menos Significativo).
- \subsec Cadena (|'bla'|\/).
- Una cadena es la represtaci\'on \ASCII/ de una secuencia de caracteres que se
- escribe entre comillas simples |''|. El valor de tales tipos de cadena es
- un puntero al primer caracter de la misma. M\'as espec\'{\i}ficamente: |'bla'|
- representa un puntero de 32~bits a un \'area de memoria en la que
- encontraremos los bytes |"b"|, |"l"| y |"a"|. En~E todas las cadenas
- terminan con un byte cero.
- \noin Las cadenas pueden contener signos de formato introducidos con una
- barra inversa |\|, ya sea para introducir en la cadena caracteres que no
- son, por alguna raz\'on, visualizables, o para usarla con funciones de
- formateo de cadenas como |WriteF()|, |TextF()| y |StringF()|, o la funci\'on
- |Vprintf()| de KickStart~2.
- \Ejemplos
- \qquad |\n|& cambio de l\'{\i}nea (\ASCII/ 10)\cr
- \qquad |\a| o |''|& ap\'ostrofe: |'| (el usado para encerrar la cadena)\cr
- \qquad |\q|& dobles comillas: |"|\cr
- \qquad |\e|& escape (\ASCII/ 27)\cr
- \qquad |\t|& tabulador (\ASCII/ 9)\cr
- \qquad |\\|& la propia barra inversa\cr
- \qquad |\0|& byte cero. De escaso uso (todas las cadenas acaban en 0)\cr
- \qquad |\b|& retorno de carro (\ASCII/ 13)\cr
- \finsma
- Adem\'as, cuando se usan con funciones de formateo:
- \Ejemplos
- \qquad |\d|& escribe un n\'umero decimal\cr
- \qquad |\h|& escribe un n\'umero hexadecimal\cr
- \qquad |\s|& escribe una cadena\cr
- \qquad |\c|& escribe un caracter\cr
- \qquad |\z|& fija el byte de relleno al caracter |0|\cr
- \qquad |\l|& ajusta a el campo a la izquierda\cr
- \qquad |\r|& ajusta a el campo a la derecha (ambos act\'uan como interruptores)\cr
- \finsma
- A los c\'odigos |\d|, |\h| y |\s| les pueden seguir especificadores de campo:
- \Ejemplos
- \qquad |[x]|& indica el ancho exacto del campo, |x|\cr
- \qquad |(x,y)|& indica el ancho m\'{\i}nimo (|x|) y m\'aximo (|y|), s\'olo con cadenas\cr
- \Ejemplos
- Ejemplo:&escribir un n\'umero hexadecimal con 8 posiciones y ceros delante:\cr
- &|WriteF('\z\h[8]\n',num)|\cr
- \finsma
- Una cadena se puede extender sobre varias l\'{\i}neas continu\'andolas con un
- signo |+| y un \<|lf|>:
- \begintt
- 'esta es una cadena deliberadamente larga que ' +
- 'esta dividida en dos lineas separadas'
- \endtt
- \subsec Lista (|[1,2,3]|\/) y lista con tipos.
- Una lista inmediata es la forma constante del tipo de datos |LIST|a, de
- la misma forma que una |'cadena'| es la forma constante de los tipos de
- datos |STRING| ({\it cadena}\/) o |ARRAY OF CHAR| ({\it arreglo de caracteres}\/).
- \Ejemplos
- Ejemplo:&|[3,2,1,4]|\cr
- \finsma
- Es una expresi\'on que tiene como valor un puntero a una lista ya
- inicializada. La representaci\'on en memoria de una lista es compatible
- con un |ARRAY OF LONG|, con informaci\'on extra sobre la longitud en un
- offset negativo. Puedes usar estas listas inmediatas en cualquier lugar
- en el que una funci\'on espere un |PTR| a un arreglo de valores de 32~bits,
- o una lista.
- \Ejemplos
- Ejemplos:&|['string',1.0,2.1]|\cr
- &|[WA_FLAGS,1,WA_IDCMP,$200,WA_WIDTH,120,WA_HEIGHT,150,TAG_DONE]|\cr
- \subsec Celdas-lisp (|<a|\||b>|\/).
- Sobre \'estas es mejor que mires en el apartado sobre {\sl Celdas-Lisp y
- funciones de celdas}.
- \endchapter\saltacap
- \beginchapter Cap\'{\i}tulo 4. Operadores
- \subsec Matem\'aticos (|+ - * /|\/).
- Estos operadores infijos combinan una expresi\'on con otro valor para
- obtener un nuevo valor. ``|-|'' se puede usar como primera parte de una
- expresi\'on, lo cual implica un~0\nota{es decir, |-exp| equivale a |0-exp|.}.
- Tambien hay que se\~nalar que por omisi\'on |*| y |/| son operadores de 16~bits.
- \Ejemplos
- Ejemplos:&|1+2, MAX-1*5, -a , -b+1|\cr
- \finsma
- Es interesante conocer los procedimientos |Mul()| y |Div()|, que
- realizan aritm\'etica de 32~bits, as\'{\i} como la sobrecarga de operadores para poder
- utilizarlos con n\'umeros reales. Todo esto se detallar\'a en pr\'oximos cap\'{\i}tulos.
- \subsec Comparaci\'on (|= <> > < >= <=|\/).
- Igual que los operadores matem\'aticos, con la diferencia de que los
- resultados son, o |TRUE| (cierto, valor de 32~bits |-1|), o |FALSE| (falso).
- Tambi\'en se pueden sobrecargar para operar con reales.
- \subsec L\'ogica y con bits (|AND OR|\/).
- Estos operadores pueden combinar valores de verdad para obtener unos
- nuevos, o realizar operaciones |AND| y |OR| con bits.
- \Ejemplos
- Ejemplos:&|(a>1) AND ((b=2) OR (c>=3)) /* logica */|\cr
- &|a:=b AND $FF /* con bits */|\cr
- \subsec (|SIZEOF \^{} -- ++ ` |$\tt \{\}$).
- \item{$-$} |SIZEOF |\<identobjeto>
- \item{} Simplemente retorna el tama\~no de cierto objeto o |CHAR/INT/LONG|.
- \espacio
- \item{} Ejemplo:\quad |SIZEOF newscreen + SIZEOF INT|
- \espacio
- \item{$-$} $\{$\<var>$\}$
- \item{} Retorna la direcci\'on de una variable o etiqueta. Este es el operador
- que usar\'{\i}as para pasar una variable como argumento de una fucni\'on por
- referencia, en lugar de por valor, que es la forma por omisi\'on en E.
- \item{} Ejemplo:\quad |Val(input,{x})|
- \espacio
- \item{$-$} |^|\<var>
- \item{} El compa\~nero de |{}|, escribe o lee variables que se han pasado por
- referencia. Tambi\'en se puede usar para {\it leer {\rm o} escribir}
- de forma directa valores |LONG| de memoria, si \<var> es un puntero
- a tal valor.
- \ejemplos
- \qquad Ejemplos:&|^a:=1 b:=^a|\cr
- &|PROC set(var,exp) -> Funcion propia de asignacion...|\cr
- &| ^var:=exp -> Para ser llamada con set({a},1),|\cr
- &|ENDPROC -> de forma que equivale a : `a:=1'|\cr
- \finsma
- \item{$-$} \<varexp>|++| y \<varexp>|--|
- \item{} Incrementa (|++|) o decrementa (|--|) el puntero que se denota con
- \<varexp> en el tama\~no de los datos a los que apunta. Esto tiene el
- efecto de que ese puntero apuntar\'a al elemento siguiente o anterior.
- Cuando se usa con variables que no son punteros, esas se modificar\'an
- simplemente en uno. Se\~nalar que |++| siempre act\'ua despu\'es del
- c\'alculo de \<varexp>, |--|, sin embargo, act\'ua {\it antes}.
- \ejemplos
- \qquad Ejemplos:&|a++ |, devuelve el valor de |a|, y luego incrementa |a|.\cr
- &|sp[]--|, decrementa puntero |sp| en 4 (|ARRAYs OF LONG|),\cr
- &| |, y luego lee el valor al que apunta |sp|.\cr
- \finsma
- \item{$-$} |`|\<exp>
- \item{} Se le llama expresi\'on entrecomillada, del {\sc LISP}. \<exp> no se
- eval\'ua, pero en su lugar devuelve la direcci\'on de la expresi\'on, que
- se puede evaluar m\'as tarde cuando se necesite.
- \subsec Triplete (|IF THEN ELSE|\/).
- El operador |IF| tiene una funci\'on similar a la sentencia |IF|, la \'unica
- diferencia es que selecciona entre dos expresiones en vez de entre dos
- sentencias o bloques de sentencias. Igual que el operador |x?y:z| del~C.
- \Ejemplos
- &|IF| \<expbool> |THEN| \<exp1> |ELSE| \<exp2>\cr
- retorna \<exp> o \<exp2>, dependiendo de \<expbool>.
- \noin Por ejemplo, en vez de:
- \ejemplos
- &|IF a<1 THEN b:=2 ELSE b:=3|\cr
- &|IF x=3 THEN WriteF('x es 3\n') ELSE WriteF('x es otra cosa\n')|\cr
- puedes escribir:
- \ejemplos
- &|b:=IF a<1 THEN 2 ELSE 3|\cr
- &|WriteF(IF x=3 THEN 'x es 3\n' ELSE 'x es otra cosa\n')|\cr
- \subsec Estructura ({|.|}).
- \<ptrAobjeto>|.|\<miembrodeobjeto> construye una \<expvar>. El puntero debe
- declararse |PTR TO| \<objeto> o |ARRAY OF| \<objeto> y el miembro debe ser
- un identificador legal de objeto. Fij\'ate que el leer un subobjeto de un
- objeto de esta forma resulta en un puntero a ese objeto.
- \Ejemplos
- Ejemplos:&|estatarea.userdata:=1 rast:=mipantalla.rastport|\cr
- \finsma
- Si el miembro que selecciona es de tipo |PTR TO| \<tipo>, puedes usar
- ``|.|'' y |[]| para referirte a nuevos valores. Si seleccionas un |ARRAY| o
- una subestructura en un |OBJECT|, el resultado es de nuevo un |PTR|.
- \subsec Arreglos (|[]|).
- \<var>|[|\<exp\'{\i}ndice>|]| (es una \<expvar>). Este operador lee el valor del
- arreglo al que apunta \<var>, de \'{\i}ndice\nota{en un arreglo de $n$ elementos,
- el \'{\i}ndice var\'{\i}a entre $0\ldots n\!-\!1$} \<exp\'{\i}ndice>. El \'{\i}ndice puede ser
- pr\'acticamente cualquier expresi\'on. Debemos saber que |[]| es una
- abreviatura de |[0]|.
- \Ejemplos
- Ejemplos:&|a[1]:=10 |, pone el segundo elemento a 10.\cr
- &|x:=table[y*4+1]|, lee del arreglo.\cr
- &|x.y[3] |, accede al arreglo dentro de un objeto.\cr
- \subsec Operador real (|!|\/).
- \<exp>|!|\<exp>. Convierte una espresi\'on de entero a real y viceversa, y
- sobrecarga los operadores |+ - * / = <> < > <= >=| con equivalentes para
- reales.
- \subsec Expresiones de asignaci\'on (|:=|\/).
- La asignaci\'on (dar un valor a una variable) existe como sentencia y como
- expresi\'on. La \'unica diferencia es que la versi\'on como sentencia tiene la
- forma \<expvar>|:=|\<exp> y la expresi\'on \<var>|:=|\<exp>. Esta \'ultima
- tiene el valor de \<exp> como resultado.
- \noin F\'{\i}jate en que como \<var>|:=| tiene lugar en una expresi\'on, a menudo
- tendr\'as que ponerla entre par\'entesis para forzar su correcta interpretaci\'on,
- como:
- \ejemplos
- &|IF mem:=New(100)=NIL THEN error()|\cr
- se interpreta como:
- \ejemplos
- &|IF mem:=(New(100)=NIL) THEN error()|\cr
- y que no es lo que quieres: |mem| debe ser un puntero, no un booleano.
- Lo que se debe escribir es:
- \ejemplos
- &|IF (mem:=New(100))=NIL THEN error()|\cr
- Es una buena costumbre escribir entre par\'entesis cualquier expresi\'on de
- asignaci\'on que forme parte de otra, siempre que otras construcciones
- como |bla(a:=1)|, |b:=a:=1|,~\dots, no hayan eliminado la ambig\"uedad.
- \subsec Secuenciamiento (|BUT|\/).
- El operador de secuenciamiento |BUT| permite la escritura de dos expresiones
- en una construcci\'on que s\'olo permite una. A menudo, al escribir
- expresiones\b/llamadas a funciones complejas, a uno le gustar\'{\i}a realizar una
- segunda cosa sobre la marcha, como una asignaci\'on.
- \Ejemplos
- \qquad Sintaxis:&\<exp1> |BUT| \<exp2>\cr
- implica: eval\'ua \<exp1>, pero retorna el valor de \<exp2>.
- \Ejemplos
- Ejemplo:&|mifunc((x:=2) BUT x*x)|\cr
- \finsma
- \item{} assigna el valor 2 a |x| y luego llama a mifunc con |x*x|.
- Los |()| entorno a la asignaci\'on son necesarios para impedir
- que el operador |:=| tome |2 BUT x*x| como expresi\'on.
- \subsec Reserva Din\'amica de Memoria (|NEW|\/).
- El operador |NEW| es un poderoso operador para la reserva din\'amica de
- memoria. Supongamos que tenemos en alguna parte de nuestro c\'odigo
- |DEF p:PTR TO| \<cualquierobjeto> y |q:PTR TO INT|, entonces:
- \ejemplos
- &|NEW p|\cr
- es una expresi\'on que reservar\'a memoria para el tama\~no del objeto al que
- apunta |p|, y la inicializa con 0. El puntero resultante se colocar\'a en
- |p|, adem\'as de ser el valor de la expresi\'on. Si |NEW| no puede obtener la
- memoria, \'este lanzar\'a una excepci\'on |"NEW"|. Por lo tanto, |NEW p| es
- practicamente equivalente a:
- \ejemplos
- &|IF (p:=New(SIZEOF cualquierobjeto))=NIL THEN Raise("MEM")|\cr
- con la diferencia de que |p| nunca recibe un valor si se lanza alguna
- excepci\'on, y que lo primero es evidentemente una expresi\'on, y no una
- sentencia.
- \noin Pero incluso hay m\'as: se pueden reservar arreglos din\'amicamente:
- \ejemplos
- &|NEW p[10] -> arreglo de 10 objectos|\cr
- &|NEW q[a+1] -> arreglo de INT, con tama\~no calculado en ejecucion|\cr
- (esto no funciona al instanciar clases)
- \noin Algunas veces el problema de expresiones de lista |[1,2,3]| es que son
- est\'aticas, y al usar \'estas para construir estructuras de datos grandes ser\'{\i}a
- conveniente crearlas en tiempo de ejecuci\'on. Se podr\'{\i}a utilizar el
- equivalente din\'amico de las listas:
- \ejemplos
- &|p:=[1,2,3]:cualquierobj -> estructura estatica|\cr
- &|p:=NEW [1,2,3]:cualquierobj -> !`reservado dinamicamente!|\cr
- Esto funciona tanto con listas como con listas con tipo, y tambi\'en con arreglos:
- \ejemplos
- &|NEW [1,2,3] -> lista const, dinam. (nota: !`no como varlista!)|\cr
- &|NEW [1,2,3]:obj -> objeto|\cr
- &|NEW [1,2,3]:INT -> arrreglo de INTs|\cr
- \finsma
- La liberaci\'on de memoria reservada con cualquiera de las variaciones de
- |NEW| se realiza de forma autom\'atica al final del programa, o a mano con
- |END| o |FastDispose()|\nota{a excepci\'on de cuando se hab\'{\i}a utilizado |NEW|\<lista>,
- que necesita |FastDisposeList()|}.
- \noin Si usas |NEW [...]:|\<obj>, y el n\'umero de campos es menor que el
- que tiene el objeto, se a\~nadir\'an campos |0/NIL/"\0"| o lo que sea. Esto nos
- permite extender los objetos sin tener problemas con reservas como estas.
- (f\'{\i}jate en que esto es diferente de las |[...]:|\<obj> est\'aticas)
- \noin Cuando usas |NEW| como sentencia, le pueden seguir un n\'umero
- indeterminado de punteros, por ejemplo, lo siguente es v\'alido:
- \ejemplos
- &|NEW a,b.create(),c|\cr
- \finsma
- \subsec Unificaci\'on (|<=>|\/).
- La unificaci\'on permite un estilo de programaci\'on totalmente diferente, y que
- te ser\'a familiar si estas acostumbrado a la programaci\'on L\'ogica (ProLog),
- ecuacional o funcional (Miranda\b/Gofer\b/Haskell). La mayor\'{\i}a de nosotros,
- cuando usamos estructuras\b/arreglos para lo que sea, obtenemos valores de
- ellas por selecci\'on (|.| y |[]|), sin embargo, en esos lenguajes se usa un
- patr\'on de concordancias. En~E:
- \<exp> |<=>| \<exp\_uni>
- \noin\<exp> puede ser cualquier expresi\'on, aunque en~v3 s\'olo es realmente
- \'util si es de alguna manera un puntero a una lista. \<exp\_uni> es el
- patr\'on que se usa para hacer que concuerde (o unifique) \<exp>, las
- variables toman sus respectivos valores. Si algo no concuerda, ninguna
- variable toma valor y la expresi\'on tiene como resultado |FALSE|\null{}. En otro
- caso |TRUE|.
- \Ejemplos
- Ejemplo:&|a:=[1,2,3]|\cr
- &| ....|\cr
- &|IF a <=> [1,x,y] THEN ...|\cr
- \finsma
- Esto tendr\'a \'exito con |x=2| e |y=3|. Si la lista tuviera otra longitud que
- no fuera 2, la unificaci\'on tambi\'en fallar\'{\i}a. El echo de que |a| sea una lista
- es algo de lo que deber\'as asegurarte por t\'{\i} mismo, |EC| simplemente intentar\'a
- hacer que \<exp\_uni> encaje con el valor, sea cual sea, que obtenga de \<exp>.
- \Ejemplos
- Ejemplos |FALSE|:&|a <=> [1,x] -> longitud de lista erronea|\cr
- &|a <=> [1,4,x] -> 4=2 falla|\cr
- &|'bla' <=> [1,2] -> impredecible (?`caida del sistema?)|\cr
- \finsma
- Lo divertido de la unificaci\'on en que puedes hacer unificaciones realmente
- complejas, y que si tomas el primer campo (u otro) como constante, indicando
- el tipo de estructura que representa, tienes una buena forma de tipos
- din\'amicos. !`Y todo el tiempo sin usar punteros!
- \noin Un ejemplo m\'as interesante:
- \ejemplos
- &|[BLA,[1,'burp'],['bla',"bla"]] <=> [BLA,[1,x],y]|\cr
- unifica:
- \ejemplos
- &|x='burp', y=['bla',"bla"]|\cr
- o incluso:
- \ejemplos
- &|IF miexp <=> [PLUS,[MUL,a,1],[SUBS,[PLUS,c,d],e]] THEN RETURN a+c+d-e|\cr
- \finsma
- Puede que sea un ejemplo tonto, pero uno se puede imaginar cosas como esta
- en el optimizador de c\'odigo de un compilador. Es lo mismo que este
- fragmento de c\'odigo tradicional:
- \begintt
- IF ListLen(miexp)=3
- IF myexp[]=PLUS
- IF ListLen(dummy:=miexp[1])=3
- IF (dummy[]=MUL) AND (dummy[2]=1)
- a:=dummy[1]
- IF ListLen(dummy:=miexp[2])=3
- IF dummy[]=SUBS
- e:=dummy[2]
- IF ListLen(dummy2:=dummy[1])=3
- IF dummy2[]=PLUS
- c:=dummy2[1]
- d:=dummy2[2]
- RETURN a+c+d-e
- ENDIF
- ENDIF
- ENDIF
- ENDIF
- ENDIF
- ENDIF
- ENDIF
- ENDIF
- \endtt
- S\'olo que de una forma un poco m\'as \'optima. Como ves, hay mucho poder
- expresivo entorno a la unificaci\'on comparada con la programaci\'on tradicional
- basada en selecci\'on.
- \noin De momento, lo \'unico permitido en la unificaci\'on son listas sin tipo,
- constantes (enteras), variables y Celdas-LISP\null{}. En el futuro veremos esto
- ampliado a cadenas, listas con tipo\b/objetos, e incluso expresiones.
- \subsec Mutaci\'on de punteros (|::|\/).
- Cuando escribes una expresi\'on como ``|p|'', donde |p| es un |PTR TO| \<objeto>,
- \'este te permite referirte a \'el como tal. El operador mutador de
- punteros te permite cambiar tal tipo en el momento (al vuelo):
- \ejemplos
- &|DEF p:PTR TO mp -> puerto de mensajes|\cr
- \Esptab
- &|p.sigbit -> accede a el|\cr
- &|p::ln.name -> accede al puntero como si fuera un nodo|\cr
- \finsma
- Esto es muy \'util para punteros que pueden apuntar a diferentes tipos de
- cosas u objetos que forman parte de otros, cuando, por supuesto, s\'olo es
- posible una declaraci\'on.
- \noin Una segunda forma de uso es en |OBJECT|os que tienen miembros
- declarados como |LONG|, que en realidad son punteros. Puedes darle un tipo
- al vuelo para hacer referencia a \'el de todas formas:
- \ejemplos
- &|miventana.userport::mp.sigbit|\cr
- \finsma
- Aqu\'{\i} el |OBJECT|o ventana tiene un |userport| definido como |LONG|, por lo que
- no podr\'as hacer referencia a \'el normalmente.
- \endchapter\saltacap
- \beginchapter Cap\'{\i}tulo 5. Sentencias
- Como se sugeri\'o en el cap\'{\i}tulo sobre el formato del c\'odigo E, generalmente una
- sentencia se declara en una l\'{\i}nea propia, aunque se pueden poner varias
- sentencias en un misma l\'{\i}nea separ\'andolas con un punto y coma, de la
- misma forma que una s\'ola sentencia se puede repartir entre varias l\'{\i}neas
- si se finaliza cada una de ellas con una coma ``|,|''.
- \Ejemplos
- Ejemplos:&|a:=1; WriteF('!`hola!\n')|\cr
- &|DEF a,b,c,d,|\cr
- &| e,f,g|\cr
- \Ejemplos
- Las sentencias pueden ser:&$-$ asignaciones\cr
- &$-$ condicionales, |FOR| y similares.\cr
- &$-$ expresiones void\cr
- &$-$ etiquetas\cr
- &$-$ instrucciones en ensamblador\cr
- \finsma
- La coma es el principal caracter para indicar que no quieres finalizar
- la sentencia con el siguiente cambio de l\'{\i}nea, aunque a partir de la
- versi\'on~3, cualquier elemento ({\it token}) que no pueda ir legalmente al final
- de una l\'{\i}nea provoca la continuaci\'on de la sentencia. Es m\'as, si no han
- sido cerrados todos los |[| y |(| de una sentencia, \'esta tambi\'en
- continuar\'a en las siguientes l\'{\i}neas.
- \Ejemplos
- Ejemplos de tales elementos: &|+ - * / =|\cr
- &|< >= <=|\cr
- &|:= . <=> :: -> hay otros, pero|\cr
- &|{ [ ( -> estos son los|\cr
- &|AND OR BUT THEN IS -> los mas utiles.|\cr
- Ejemplo de c\'odigo entre corchetes:&|a:=[|\cr
- &| [1,2],|\cr
- &| [3,4]|\cr
- &| ] -> la asignacion finaliza aqui.|\cr
- \subsec Etiquetas y Saltos (|JUMP|\/).
- Las etiquetas son identificadores de alcanze global que incorporan
- |:|, como en:\qquad |mietiqueta:|
- \noin Se pueden utilizar con instrucciones como |JUMP|, y para hacer referencia
- a datos est\'aticos. Se pueden usar para salir de cualquier tipo de
- {\it bucle}\nota{aunque no recomiendo esta t\'ecnica.}, pero no de los procedimientos.
- En los programas~E normales se utilizan principalmente con el ensamblador
- \hbox{en-l\'{\i}nea}. Las etiquetas siempre son visibles globalmente.
- \Ejemplos
- \qquad Sintaxis:&|JUMP |\<etiqueta>\cr
- \finsma
- Contin\'ua la ejecuaci\'on en \<etiqueta>. No es recomendable usar esta
- instrucci\'on, est\'a disponible para ser utlizada s\'olo en casos en los que
- de otra forma se incrementar\'{\i}a la complejidad del programa.
- \Ejemplos
- Ejemplo:&|IF seacabo THEN JUMP termina|\cr
- &|/* otras partes del programa */|\cr
- \Esptab
- &|termina:|\cr
- \subsec Asiganci\'on (|:=|\/).
- La forma b\'asica de asignaci\'on es:
- \Ejemplos
- \qquad Sintaxis:&\<var>| := |\<exp>\cr
- \Ejemplos
- Ejemplos:&|a:=1, a:=mifunc(), a:=b*3|\cr
- \finsma
- En E se pueden asignar varias variables de una vez, cuando \<exp> es
- una funci\'on que devuelve varios valores de retorno.
- \subsec Mnemot\'ecnicos ensamblador.
- El ensamblador en-l\'{\i}nea es una parte real del lenguaje, no necesita
- introducirse mediante bloques especiales |"ASM"| o similares, como es normal
- en otros lenguajes, y tampoco necesita ensambladores independientes para
- ensamblar el c\'odigo. Esto tambi\'en signifca que obedece las reglas de
- sintaxis de~E, etc.
- \noin Ejemplo:
- \begintt
- DEF a,b
- MOVEQ #1,D0 /* algunas sentencias de ensamblador */
- MOVE.L D0,a /* a:=1+b */
- ADD.L b,a
- WriteF('a=\d\n',a) /* y escribira 3 */
- \endtt
- \subsec Conditionales (|IF|\/).
- \Ejemplos
- \qquad Sintaxis:&|IF |\<exp>| THEN |\<sentencia>| [ ELSE |\<sentencia>| ]|\cr
- \qquad o: &|IF |\<exp>\cr
- &| |\<sentencias>\cr
- &|[ ELSEIF |\<exp>| /* puede haber varios ELSEIF */|\cr
- &| |\<sentencias>| ]|\cr
- &|[ ELSE ]|\cr
- &| |\<sentencias>\cr
- &|ENDIF|\cr
- \finsma
- Construye un bloque condicional. Se\~nalar que hay dos formas generales
- para esta sentencia, una versi\'on de una l\'{\i}nea y la otra de varias.
- \subsec Para (|FOR|\/).
- \Ejemplos
- \qquad Sintaxis:&|FOR |\<var>| := |\<exp>| TO |\<exp>| STEP |\<paso>| DO |\<sentencia>\cr
- \qquad o: &|FOR |\<var>| := |\<exp>| TO |\<exp>| STEP |\<paso>\cr
- &| |\<sentencias>\cr
- &|ENDFOR|\cr
- \finsma
- Construye un bloque ``{\sl para}'', f\'{\i}jate en las dos formas generales. \<paso>
- puede ser cualquier constante positiva o negativa, excluyendo 0, y es
- opcional.
- \Ejemplos
- Ejemplo:&|FOR a:=1 TO 10 DO WriteF('\b\n',a)|\cr
- \finsma
- El cuerpo del |FOR| puede contener sentencias |EXIT|:
- \Ejemplos
- \qquad Sintaxis:&|EXIT| \<expbool>\cr
- que te permite salir del bucle si \<expbool> es cierta.
- \subsec Mientras (|WHILE|\/).
- \Ejemplos
- \qquad Sintaxis:&|WHILE |\<exp>| DO |\<sentencia>\cr
- \qquad o: &|WHILE |\<exp>\cr
- &| |\<sentencias>\cr
- &|ENDWHILE|\cr
- \finsma
- Construye un bloque ``{\sl mientras}'', el cual se repite siempre que \<exp>
- sea |TRUE|\null{}. F\'{\i}jate en las diferencias entre la versi\'on de una-l\'{\i}nea\b/una-sentencia y la versi\'on
- de varias l\'{\i}neas.
- \noin |WHILE| tambi\'en puede contener sentencias |EXIT|, como el |FOR|.
- \subsec Repite (|REPEAT|\/).
- \Ejemplos
- \qquad Sintaxis:&|REPEAT|\cr
- &| |\<sentencias>\cr
- &|UNTIL |\<exp>\cr
- \finsma
- Construye un bloque ``{\sl repite-hasta}'' que se ejecutar\'a hasta que
- \<exp>|=TRUE|\null{}. (Se\~nalar que el bloque siempre se ejecutar\'a al menos una vez)
- \Ejemplos
- Ejemplo:&|REPEAT|\cr
- &| WriteF('?`Estas seguro, seguro de salir del programa?\n')|\cr
- &| ReadStr(stdout,s)|\cr
- &|UNTIL StrCmp(s,'!`Si, por favor!')|\cr
- \finsma
- \subsec Bucle (|LOOP|\/).
- \Ejemplos
- \qquad Sintaxis:&|LOOP|\cr
- &| |\<sentencias>\cr
- &|ENDLOOP|\cr
- \finsma
- Construye un bucle infinito.
- \subsec Selecci\'on (|SELECT|\/).
- \Ejemplos
- \qquad Sintaxis:&|SELECT |\<var>\cr
- &|[ CASE |\<exp>\cr
- &| |\<sentencias>| ]|\cr
- &|[ CASE |\<exp>\cr
- &| |\<sentencias>| ] /* cualquier numero de bloques */|\cr
- &|[ DEFAULT|\cr
- &| |\<sentencias>| ]|\cr
- &|ENDSELECT|\cr
- \finsma
- Construye un bloque de selecci\'on. Se contrastar\'an varias expresiones
- con la variable, y s\'olo se ejecutar\'a el primer bloque que la satisfaga.
- El bloque por omisi\'on (|DEFAULT|) se ejecutar\'a si la variable no satisface
- a ninguna de las expresiones.
- \Ejemplos
- Ejemplo:&|SELECT caracter|\cr
- &| CASE 10|\cr
- &| WriteF('Ejem, he encontrado un cambio de linea\n')|\cr
- &| CASE 9|\cr
- &| WriteF('!`Vaya, esto debe ser un tabulador!\n')|\cr
- &| DEFAULT|\cr
- &| WriteF('?`Conoces este: "\c" ?\n',caracter)|\cr
- &|ENDSELECT|\cr
- \finsma
- Adem\'as de el ``|SELECT |\<var>'' de siempre, que trabaja con expresiones en
- las sentencias |CASE|, E~tiene un ``|SELECT |\<maxrango>| OF |\<exp>'' que funciona
- con constantes y/o rangos de constantes en el |CASE|\null{}. No s\'olo es m\'as
- potente para muchas aplicaciones, si no que es mucho m\'as r\'apido para un
- n\'umero de casos grande (generalmente~|>5|), o si los casos son igualmente
- probables. Sin embargo supone que todos los |CASE|s caen dentro de un
- rango de enteros peque\~no desde |0| a $n-1$, donde $n$ es un n\'umero razonable,
- por ejemplo |10|, o |255| para caracteres.
- \Ejemplos
- Ejemplo:&|SELECT 127 OF FgetC(stream)|\cr
- &| CASE "\n","\b"|\cr
- &| WriteF('fin de linea\n')|\cr
- &| CASE "\t"," "|\cr
- &| WriteF('espacio blanco\n')|\cr
- &| CASE "0" TO "9"|\cr
- &| WriteF('Entero\n')|\cr
- &| CASE "A" TO "Z", "a" TO "z", "_"|\cr
- &| WriteF('Identificador\n')|\cr
- &| DEFAULT|\cr
- &| WriteF('otros caracteres\n')|\cr
- &|ENDSELECT|\cr
- |DEFAULT| se ejecutar\'a no s\'olo para aquellos valores para los que no hay
- |CASE|, si no tambi\'en para los que est\'en fuera del rango, (en este ejemplo,
- de |128| a |255| y |>255| o |<0|).
- \noin Se\~nalar que la velocidad tiene un precio: ya que este |SELECT| usa
- una tabla de saltos para acceder r\'apidamente al |CASE| correcto, usar\'a
- $2*$\<maxrango> bytes, |256| en este ejemplo.
- \subsec Incremento (|INC/DEC|\/).
- \Ejemplos
- \qquad Sintaxis:&|INC |\<var>\cr
- &|DEC |\<var>\cr
- \finsma
- Es una abreviatura para \<var>|:=|\<var>|+1| y \<var>|:=|\<var>|-1|. Con la \'unica
- diferencia de que las primeras son sentencias y no retornan un valor.
- \subsec Expresiones void (|VOID|).
- \Ejemplos
- \qquad Sintaxis:&|VOID |\<exp>\cr
- \finsma
- Calcula la expresi\'on sin poner el resultado en lugar alguno. S\'olo es
- \'util para una sintaxis m\'as clara, ya que en~E, de todas formas, las
- expresiones se pueden usar como sentencias sin usar |VOID|\null{}. Sin embargo,
- esto puede causar errores dif\'{\i}ciles de apreciar, ya que, por ejemplo,
- |a:=1| asigna el valor |1| a |a|, pero |a=1| no resulta en nada como
- sentencia. E~te indicar\'a con una advertencia si eso ocurre.
- \subsec Liberaci\'on de memoria (|END|).
- |END| es el complemento de |NEW|\null{}. Cualquier puntero obtenido con |NEW| se
- debe liberar con ({\bf y s\'olo con}) |END|.
- \Ejemplos
- \qquad Sintaxis:&|END a|\cr
- \qquad o incluso\cr
- &|END a,b,c|\cr
- donde los argumentos son |PTR|s a alg\'un tipo. |END| libera el
- espacio de memoria al que se est\'a apuntando, de forma que si |a| es un
- |PTR TO LONG|, s\'olo liberar\'a 4 bytes. Esto quiere decir que si reservaste
- |a| con |NEW a[NUM]|, lo debes liberar con |END a[NUM]|.
- \noin |NEW| acepta de forma segura punteros |NIL|\null{}. Los punteros tambi\'en se
- vuelven a |NIL| tras su liberaci\'on.
- \noin Si |a| es un |PTR| a un objeto que es un instancia de una clase, |END|
- obtendr\'a din\'amicamente el tama\~no del objeto que se desea liberar de la
- clase, de forma que si tienes un objeto de clase |b| de 32 bytes, pero el
- puntero con el que lo vas a liberar es de una clase base (s\'olo 24 bytes),
- |END| liberar\'a correctamente los 32 bytes. Esto s\'olo funciona con clases.
- \noin Puedes imaginar |END p| como una macro de:
- \begintt
- p.end()
- FastDispose(p,p.classobject.virtuallen)
- p:=NIL
- ENDIF
- \endtt
- Se\~nalar que |NEW| y |END| utilizan las funciones |FastNew()| y |FastDispose()|
- (descritas en alg\'un otro cap\'{\i}tulo) que trabajan de forma bastante distinta a
- como lo hacen |NewR()| y |Dispose()|.
- \endchapter\saltacap
- \beginchapter Cap\'{\i}tulo 6. Definici\'on\\y declaraci\'on\\de funciones
- Puedes usar |PROC| y |ENDPROC| para agrupar sentencias formando tus
- propias funciones. Tales funciones pueden tener cualquier n\'umero de
- argumentos, y varios valores de retorno.
- \Ejemplos
- \qquad Sintaxis:&|PROC |\<etiqueta>| ( |\<args>|, ... )|\cr
- &|ENDPROC |\<valorretorno>|, ...|\cr
- \finsma
- Define un procedimiento con cualquier n\'umero de argumentos. Los
- argumentos son de tipo |LONG|, u opcionalmente de tipo |PTR TO |\<tipo> y no
- necesitan ning\'un tipo de declaraci\'on. Con |ENDPROC| se denota el final del
- procedimiento. Si no se d\'a un valor de retorno, se retorna 0.
- \Ejemplos
- Ejemplo:&funci\'on que retorna la suma de dos argumentos:\cr
- & | PROC suma(x,y) /* x e y son variable locales */|\cr
- & | ENDPROC x+y /* retorna el resultado */|\cr
- \esptab
- m\'as corto:&| PROC suma(x,y) IS x+y|\cr
- \seccion Definiciones locales y globales: alcance (|DEF|\/).
- Con la sentencia |DEF| puedes definir variables locales adicionales aparte
- de aquellas que son argumentos. La forma m\'as sencilla es con:
- \ejemplos
- &|DEF a,b,c|\cr
- \finsma
- que declara los identificadores |a|, |b| y |c| como variables de tu funci\'on.
- Se\~nalar que tales declaraciones deben estar al pricipio de tu funci\'on.
- \Ejemplos
- \qquad Sintaxis:&|DEF |\<declaraciones>|, ...|\cr
- declara variables. Una declaraci\'on tiene una de las siguiente formas:
- \item{$-$} \<var> \qquad\qquad (que utilizaremos a partir de ahora.)
- \item{$-$} \<var>|:|\<tipo> \qquad\qquad donde \<tipo>|=LONG, |\<identobjeto>,~\dots
- \item{$-$} \<var>|[|\<tama\~no>|]:|\<type> \qquad\qquad donde \<tipo>|=ARRAY|, |STRING|, |LIST|
- \espacio
- Los argumentos de funciones se restringen a tipos b\'asicos.
- La declaraci\'on de un tipo b\'asico puede tener una inicializaci\'on, en
- la versi\'on actual \'esta debe ser un entero (no una expresi\'on):
- \ejemplos
- &|DEF a=1,b=2|\cr
- \finsma
- Un programa est\'a formado por un conjunto de funciones, llamados
- procedimientos, |PROC|s. Cada procedimiento puede tener variables Locales,
- y el programa como un todo puede tener variables Globales. Al menos uno
- de los procedimientos del programa debe ser el ``|PROC main()|'', ya que \'este
- es el m\'odulo en el que comienza la ejecuci\'on. Un programa sencillo puede
- paracerse a:
- \begintt
- DEF a, b /* definicion de variables globales */
- PROC main() /* las funciones en orden aleatorio */
- bla(1)
- ENDPROC
- PROC bla(x)
- DEF y,z /* posiblemente variables locales propias */
- ENDPROC
- \endtt
- \espacio
- Para resumir, las definiciones locales son las que se hacen al
- comienzo de los procedimientos, y que s\'olo son visibles dentro de esa
- funci\'on. Las definiciones globales se realizan antes del primer
- procedimiento, de tu c\'odigo fuente, y son visibles globalmente. Puede
- haber variables locales con el mismo nombre que variables globales (y por
- supuesto, lo mismo con variables locales de dos funciones diferentes), en
- cuyo caso, las variables locales tienen prioridad.
- \seccion ENDPROC/RETURN.
- Como se indic\'o con anterioridad, |ENDPROC| marca el final de la
- definici\'on de una funci\'on, y puede retornar un valor. De forma opcional,
- |RETURN| se puede usar en cualquier punto de la funci\'on para salir de
- ella, y si se usa en |main()| provocar\'a la finalizaci\'on del programa.
- \Ejemplos
- \qquad Sintaxis:&|RETURN [|\<valorretorno>|]|\cr
- \finsma
- Ejemplo:
- \begintt
- PROC obtenrecursos()
- /* ... */
- IF error THEN RETURN FALSE /* algo fue mal ---> sal y falla */
- /* ... */
- ENDPROC TRUE /* llegamos hasta aqui, entonces retorna TRUE */
- \endtt
- \espacio
- Una versi\'on reducida de la definici\'on de una funci\'on es:
- \ejemplos
- &|PROC |\<etiqueta>| ( |\<arg>|, ... ) RETURN |\<exp>\qquad (o |IS| en vez de |RETURN|)\cr
- Estas son definiciones de funciones que s\'olo realizan peque\~nas
- computaciones, como funciones factoriales y parecidas: ({\it one-liners} |:-)|)
- \ejemplos
- &|PROC fac(n) IS IF n=1 THEN 1 ELSE fac(n-1)*n|\cr
- \seccion Funci\'on |main()|.
- El |PROC| llamado |main| tiene importancia porque es la primera funci\'on
- que se ejecuta; se comporta como las dem\'as funciones, y tambi\'en puede
- tener variables locales. |main()| no tiene argumentos: los argumentos de
- la l\'{\i}nea de comandos se ofrecen en la variable de sistema |arg|, y
- tambi\'en se pueden analizar con |ReadArgs()|.\nota{funci\'on de |dos.library|.}
- \seccion Variables del sistema predefinidas.
- Las siguientes variables globales siempre est\'an disponibles en tu programa,
- se les llama variables del sistema.
- \smallskip
- \halign{{\tt#}\hfil&
- \quad\vtop{\parindent=0pt\hsize=24pc\hangindent=0pt\strut#\strut}\cr
- arg&Como se dijo antes, tiene un puntero a un cadena acabada
- en cero, con los argumentos de la l\'{\i}nea de comandos.
- No uses esta variable si prefieres usar |ReadArgs()|.\cr
- stdout&Contiene el file-handle para la salida estandard. Si tu
- programa fue iniciado desde el Workbench, de forma que no
- hay salida-de-shell disponible, |WriteF()| abrir\'a una
- ventana |CON:| para t\'{\i} y pondr\'a su file-handle en esta variable.\cr
- stdin&file-handle para la entrada estandard.\cr
- conout&Aqu\'{\i} es donde se pone el file-handle, y la ventana de
- consola se cerrar\'a de forma autom\'atica cuando tu programa
- finalice. (mira en |WriteF()| sobre la utilizaci\'on de estas dos
- variables de forma apropiada.)\cr
- execbase,&Estas cuatro variables se ofrecen siempre inicializadas con el valor apropiado.\cr
- dosbase,\cr
- gfxbase,\cr
- intuitionbase\cr
- stdrast&Puntero al |rastport| standard para usarlo con tu programa,
- o |NIL|\null{}. La usan las funciones gr\'aficas internas (|Line()|).\cr
- wbmessage&Puntero a mensaje recibido si el programa se inici\'o desde
- Wb. Se puede usar como booleano para detectar si el programa
- se inici\'o desde el Wb, o para comprobar cualquier
- argumento que se seleccion\'o con \<|shift|> junto con el icono
- de la aplicaci\'on. Mira |WbArgs.e| en directorio |Src/Args/|
- para ver como utilizar de forma correcta esta variable.\cr
- \seccion Argumentos por omisi\'on de funciones.
- Los argumentos por omisi\'on permiten especificar un valor por omisi\'on
- para uno o m\'as argumentos de una funci\'on, para el caso en el que la
- funci\'on se llama con menos argumentos que par\'ametros. Por ejemplo, un
- procedimiento como:
- \ejemplos
- &|PROC bla(a,b=1,c=NIL)|\cr
- \ejemplos
- se puede llamar con:& que equivale a:\cr
- \qquad| bla(a,b,c)|& | bla(a,b,c)|\cr
- \qquad| bla(a,b)|& | bla(a,b,NIL)|\cr
- \qquad| bla(a)|& | bla(a,1,NIL)|\cr
- \finsma
- Esto puede ser muy \'util, y tambi\'en puede expresar algo sobre la
- funci\'on del procedimiento, por ejemplo, que la mayor\'{\i}a de las veces se le
- llamar\'a con |NIL|, as\'{\i} que, ?`por qu\'e no suprimir ese argumento de la
- llamada por claridad?
- \noin Esa tambi\'en es una raz\'on para no sobreutilizar los argumentos por
- omisi\'on: no empieces a dejar fuera valores no esenciales para los
- procedimientos por mera pereza, si piensas que un parametro no tiene
- realmente un valor por defecto.
- \espacio
- Para impedir que las llamadas con menos argumentos sean amb\'{\i}guas,
- s\'olo pueden declararse como arguementos por omisi\'on los \'ultimos $0\ldots n$
- par\'ametros de un |PROC| de $n$ par\'ametros. Por ejemplo,\quad|PROC bla(a,b=1,c)| es ilegal
- (!`aunque en esos casos siempre puedes reordenar los par\'ametros!).
- \espacio
- Los argumentos que se proporcionan en una llamada se rellenan de
- izquierda a derecha, y los argumentos que falten se a\~naden con argumentos
- por omisi\'on seg\'un sea necesario.
- \seccion Valores de retorno m\'ultiples.
- En E puedes retornar cualquier n\'umero de valores de retorno (m\'ax.~3 en
- \E/ por razones de implementaci\'on). ?`C\'omo?
- \Ejemplos
- \qquad Sintaxis:&|RETURN [|\<exp>|,|\<exp>|,|\<exp>|]|\quad(o |ENDPROC|, por supuesto)\cr
- \Ejemplos
- Ejemplo:&|PROC sincos(rad)|\cr
- &| DEF sin,cos|\cr
- &| /* cualquier computacion necesaria */|\cr
- &|ENDPROC sin,cos|\cr
- se llama con:
- \ejemplos
- &|s,c:=sincos(3.14)|\cr
- &|s:=sincos(1.00)|\cr
- \finsma
- Como puedes ver, hay una nueva sentencia de la forma:
- \ejemplos
- &\<var>|, ... := |\<exp>\cr
- donde \<exp> pr\'acticamente s\'olo tiene sentido como llamada a funci\'on.
- \espacio
- Se\~nalar dos cosas:
- \item{$-$} Tu decides el n\'umero de argumentos que quieres recibir. Esto tiene
- sentido cuando el primer valor de retorno es el pricipal, y el
- segundo\b/tercero representan informaci\'on adicional, que puede ser
- importante s\'olo para algunos llamadores.
- \item{$-$} Esta forma es una {\sl sentencia}. Esto significa que cuando llamas a
- |sincos()| como parte de otra expresi\'on, s\'olo se usa el primer (el
- regular) valor de retorno:
- \item{} |fun(sincos(1.0))|
- \seccion Valores de funci\'on.
- Con v3, tambi\'en puedes tener funciones como valores, y usar \'estos
- l\'{\i}bremente. Son diferentes de las expresiones entrecomilladas, ya que se
- llaman como los procedimientos normales.
- \Ejemplos
- Ejemplo:&|fun:={miproc} -> obtener ptr a PROC|\cr
- &| ....|\cr
- &|fun(1,2,3) -> aplicar a args, como un PROC normal|\cr
- \finsma
- Notas:
- \item{$-$} Debes asegurarte de que el |PROC| del que tienes el puntero tiene el
- mismo n\'umero de argumentos que los que le vas a aplicar. El compilador
- no puede comprobar esto por t\'{\i}.
- \item{$-$} Peor tadav\'{\i}a: debes asegurarte de que el puntero es en realidad un
- puntero a |PROC|\null{}. Hay una advertencia del compilador que te puede ayudar
- con esto.
- \endchapter\saltacap
- \beginchapter Cap\'{\i}tulo 7. Declaraci\'on\\de constantes
- \Ejemplos
- \qquad Sintaxis:&|CONST |\<declaraciones>|, ...|\cr
- te permite declarar una constante. Una declaraci\'on es como sigue:
- \ejemplos
- &\<ident>|=|\<valor>\cr
- \finsma
- Las constantes deben ir en may\'usculas, y el resto del program las trata como \<valor>.
- \Ejemplos
- Ejemplo:&|CONST MAX_LINEAS=100, ER_NOMEM=1, ER_NOFICHERO=2|\cr
- \finsma
- No puedes declarar constantes en t\'erminos de otras que se est\'en
- declarando en la misma sentencia |CONST|, debes ponerlas en la siguiente sentencia.
- \noin Las declaraciones |CONST|, |ENUM| y |SET| siempre son globales, es decir, no
- se pueden declarar constantes locales a un procedimiento. El mejor lugar
- para poner las declaraciones de constantes es al principio de tu fuente,
- aunque |EC| tambi\'en te permite ponerlas entre dos |PROC|s, por ejemplo.
- \seccion Enumeraciones (|ENUM|).
- Las enumeraciones son un tipo espec\'{\i}fico de constante al que no es
- necesario darle valores, simplemente est\'an en un rango entre $0\ldots n$, siendo
- la primera $0$. De todas formas, puedes utilizar |=|\<valor> en
- cualquier punto de la enumeraci\'on para cambiar o reiniciar el contador de valores.
- \Ejemplos
- Ejemplos:&|ENUM CERO, UNO, DOS, TRES, LUNES=1, MARTES, MIERCOLES|\cr
- &|ENUM ER_NOFICHERO=100, ER_NOMEM, ER_NOVENTANA|\cr
- \seccion Conjuntos (|SET|).
- Los conjuntos son tambi\'en como las enumeraciones, con la diferencia de
- que en lugar de incrementar el valor ($0,1,2,\ldots$) incrementan el n\'umero de
- bit ($0,1,2,\ldots$) resultando en valores como ($1,2,4,8,\ldots$). Esto tiene la
- ventaja a\~nadida de que se pueden usar como conjuntos de banderas, tal y
- como dice la palabra clave.
- \noin Imag\'{\i}nate un conjunto como el siguiente para describir las propiedades
- de una ventana:
- \ejemplos
- &|SET SIZEGAD,CLOSEGAD,SCROLLBAR,DEPTH|\cr
- entonces, para inicializar una variable con las propiedades |DEPTH| y |SIZEGAD|:
- \ejemplos
- &|baderasvent:=DEPTH OR SIZEGAD|\cr
- y para incluir una bandera |SCROLLBAR| adicional:
- \ejemplos
- &|baderasvent:=banderasvent OR SCROLLBAR|\cr
- o para comprobar si alguna o ambas propiedades est\'an activas:
- \ejemplos
- &|IF banderasvetn AND (SCROLLBAR OR DEPTH) THEN -> lo que sea|\cr
- \seccion Constantes predefinidas.
- Las siguientes son constantes predefinidas que se pueden usar en cualquier momento:
- \ejemplos
- |TRUE|,|FALSE| & Representan los valores booleanos (|-1|,|0|).\cr
- |NIL|& (|=0|), el puntero sin incializar.\cr
- |ALL|& Con funciones de cadenas (|StrCopy()|) copia todos los caracteres.\cr
- |GADGETSIZE|& Tama\~no m\'{\i}nimo en bytes de un gadget (|Gadget()|).\cr
- |OLDFILE|,|NEWFILE|&Par\'ametros de modo para usar con |Open()|.\cr
- |EMPTY|& Usado con m\'etodos (puede convertirse en palabra clave)\cr
- |STRLEN|& Tiene la longitud de la \'ultima cadena inmediata usada.\cr
- & Ejemplo:\quad |Write(handle,'!`Hola colegas!',STRLEN) -> =14|\cr
- \endchapter\saltacap
- \beginchapter Cap\'{\i}tulo 8. El Sistema\\de Tipos
- E no posee un sistema de tipos (o sistema de tipos de datos) r\'{\i}gido,
- como el Pascal o el Modula2, incluso es m\'as flexible que el sistema de
- tipos del~C\null{}. Esto debe tenerse bien en cuenta, junto con la filosof\'{\i}a de
- que en~E todos los tipos de datos son iguales: todos los valores b\'asicos
- peque\~nos como caracteres, enteros,~\dots, tienen el mismo tama\~no de
- 32~bits, y todos los dem\'as tipos de datos, como los arreglos y las cadenas
- est\'an representados por punteros de 32~bits a ellos. De esta forma, el
- compilador de~E puede generar c\'odigo de una forma muy polim\'orfica.
- \espacio
- Las (des)ventajas son obvias:
- \item{$-$} Menor control por parte del compilador sobre errores tontos.
- \espacio
- Ventajas:
- \item{$-$} Polimorfismo a bajo nivel, crea facilmente potentes funciones gen\'ericas.
- \item{$-$} Programaci\'on flexible : sin problemas con tipos de valores de retorno
- que no coinciden y sin {\it mutaciones} ni mensajes de error superfluos.
- \item{$-$} Sin errores dif\'{\i}ciles de encontrar al mezclar tipos de datos de dife
- rentes tama\~nos.
- \espacio
- Veamos ahora los tipos de datos del lenguaje:
- \seccion B\'asico (|LONG/PTR|).
- S\'olo hay un tipo de variable b\'asico ---no complejo--- en E, el cual es
- el tipo |LONG| de 32~bits. Por ser el tipo por omisi\'on, se declarara con:
- \Ejemplos
- \qquad Sintaxis:&|DEF a:LONG|\qquad\qquad o simplemente:\quad |DEF a|\cr
- \finsma
- Este tipo de variable puede contener lo que se conoce como tipos
- |CHAR|\b/|INT|\b/|PTR|\b/|LONG| en otros lenguajes. Una variaci\'on especial de |LONG| es
- el tipo |PTR|\null{}. Este tipo es compatible con |LONG|, con la \'unica diferencia
- de que indica a qu\'e tipo apunta el puntero. Por omisi\'on, el tipo |LONG| se
- especifica como |PTR TO CHAR|.
- \espacio
- \Ejemplos
- \qquad Sintaxis:&|DEF |\<var>|:PTR TO |\<tipo>\cr
- &donde \<tipo> es o un tipo simple o uno compuesto.\cr
- \Ejemplos
- Ejemplo:&|DEF x:PTR TO INT, mipantalla:PTR TO screen|\cr
- |screen| es el nombre de un objeto definido en |intuition|\b/|screens.m|.
- \espacio
- Por ejemplo, si abres tu propia pantalla con:
- \ejemplos
- &|mipantalla:=OpenS(...) | etc.\cr
- puedes usar el puntero |mipantalla| como en |mipantalla.rastport|. Sin
- embargo, si no quieres hacer nada con la variable hasta llamar a
- |CloseS(mipantalla)|, puedes declararla simplemente como:
- \ejemplos
- &|DEF mipantalla|\cr
- \finsma
- Las declaraciones de variables pueden tener inicializaciones
- opcionales, pero s\'olo constantes enteras, no expresiones completas:
- \ejemplos
- &|DEF a=1, b=NIL:PTR TO textfont|\cr
- \seccion Simple (|CHAR/INT/LONG|).
- Los tipos simples |CHAR| (8bit) e |INT| (16bit) no se pueden usar como
- tipos para una variable b\'asica.\nota{supongo que ya sabes la raz\'on.} Sin
- embargo, se pueden usar como tipo de dato para construir |ARRAY|s de ellos,
- definir punteros a ellos, usarlos en la definici\'on de |OBJECT|os, etc.
- Mira los ejemplos de \'estos \'ultimos.
- \seccion Arreglos (|ARRAY|).
- Los arreglos de declaran indicando su longitud (en bytes):
- \ejemplos
- &|DEF b[100]:ARRAY|\cr
- esto define un array de 100 bytes. Internamente |b| es una variable de
- tipo |LONG| y un puntero a esa \'area de memoria.
- \espacio
- El tipo por omisi\'on de un elemento de arreglo es |CHAR|, aunque puede
- ser cualquier cosa especificando:
- \ejemplos
- &|DEF x[100]:ARRAY OF LONG|\cr
- &|DEF mismenus[10]:ARRAY OF newmenu|\cr
- donde |newmenu| es un ejemplo de estructura, llamados |OBJECT|os en~E\null{}. El
- acceso a los arreglos es muy sencillo, con \<var>|[|\<exps>|]|:
- \ejemplos
- &|b[1]:="a"|\cr
- &|z:=mismenus[a+1].mutualexclude|\cr
- \finsma
- Se\~nalar que el \'{\i}ndice de un arreglo de tama\~no $n$ se mueve entre $0$ y
- $n-1$, y no entre $1$ y $n$. Y tambi\'en que |ARRAY OF |\<tipo> es compatible
- con |PTR TO |\<tipo>, con la \'unica diferencia de que la variable que es un
- |ARRAY| se encuentra inicializada.
- \seccion Complejo (|STRING/LIST|).
- \item{$-$} Las cadenas (|STRING|), son similares a los arreglos, aunque se
- diferencian de ellos en que s\'olo se pueden modificar usando funciones de
- cadenas de~E; y en que contienen informaci\'on sobre su longitud, de forma
- que las funciones de cadenas pueden modificarlas de una forma segura, es
- decir: la cadena nunca puede crecer m\'as all\'a del \'area de memoria en la
- que est\'a.
- \itemitem{} Declaraci\'on:\qquad |DEF s[80]:STRING|
- \item{} El tipo de datos |STRING| (llamado cadenaE\nota{en realidad {\it estring}.}) es compatible con
- |PTR TO CHAR|, y tambi\'en con |ARRAY OF CHAR|, pero no en sentido opuesto.
- \item{$-$} Las |LIST|as se pueden entender como una mezcla entre |STRING| y |ARRAY OF LONG|\null{}.
- Es decir: esta estructura de datos mantiene una lista de
- variables |LONG| que se puede extender y acortar como los |STRING|s.
- \itemitem{} Declaraci\'on:\qquad |DEF x[100]:LIST|
- \item{} Una poderosa incorporaci\'on a este tipo de datos es que tambi\'en tiene un
- equivalente constante |[]|, de la misma forma que los |STRING|s tienen |''|.
- Una lista es compatible con |PTR TO LONG|, y por supuesto |ARRAY TO LONG|,
- aunque no en sentido contrario.
- \seccion Compuesto (|OBJECT|).
- Los |OBJECT| son como una estructura\b/clase en C/C++ o |RECORD| en Pascal.
- \Ejemplos
- Ejemplo:&|OBJECT miobj -> define un estructura de datos|\cr
- &| a:LONG -> formada por tres elementos.|\cr
- &| b:CHAR|\cr
- &| c:INT|\cr
- &|ENDOBJECT|\cr
- \Ejemplos
- \qquad Sintaxis:&|OBJECT |\<nombreobj>\cr
- &| |\<nombremiembro>| [ : |\<tipo>| ] -> cualquier numero|\cr
- &|ENDOBJECT|\cr
- donde \<tipo> es uno de los siguientes:
- \ejemplos
- &|CHAR/INT/LONG/|\<objeto>\cr
- &|PTR TO CHAR/INT/LONG/|\<objeto>\cr
- &|ARRAY OF CHAR/INT/LONG/|\<objeto>\cr
- &(|ARRAY| es abreviatura de |ARRAY OF CHAR|)\cr
- \finsma
- Al igual que las declaraciones |DEF|, omitir el tipo implica |:LONG|.
- \espacio
- Destacar que \<nombremiembro> no necesita ser un identificador \'unico y
- puede aparecer en otros objetos. Hay muchas formas de usar objetos:
- \begintt
- DEF x:miobj -> x es una estrutura
- DEF y:PTR TO miobj -> y es un puntero a la estrutura
- DEF z[10]:ARRAY OF miobj
- y:=[-1,"a",100]:miobj -> listas con tipo
- IF y.b="a" THEN /* ... */
- z[4].c:=z[d+1].b++
- \endtt
- Los elementos de los objetos se redondean a tama\~nos pares, y se ponen
- en offsets pares:
- \ejemplos
- &|OBJECT micadena -> SIZEOF de micadena es 12|\cr
- &| longitud:CHAR, datos[9]:ARRAY -> datos empieza con un offset de 2|\cr
- &|ENDOBJECT|\cr
- |PTR TO| es el \'unico tipo en |OBJECT|os que puede hacer referencia a
- otros objetos que no hayan sido declarados todav\'{\i}a.
- \Espacio
- Podr\'{\i}a parecerte interesante echar un vistazo a las caracter\'{\i}sticas
- de programaci\'on Orientada a Objetos de los |OBJECT|os.
- \seccion Inicializaci\'on.
- \item{$1.$} Siempre se inicializan a |NIL|\nota{siempre es mejor escribir |=NIL|
- en definiciones de variables que se espera que sean |NIL|.}
- \ (u otra cosa si se indica)
- \itemitem{$-$}Variables globales
- \item{$2.$} Se inicializan a |''| y |[]| respectivamente
- \itemitem{$-$} |STRING|s globales y locales
- \itemitem{$-$} |LIST|as globales y locales
- \item{$3.$} No se inicializan
- \itemitem{$-$} variables locales (a no ser que se indique explicitamente)
- \itemitem{$-$} |ARRAY|s globales y locales
- \itemitem{$-$} |OBJECT|os globales y locales
- \seccion Esencia del sistema de tipos de E.
- Esta secci\'on intenta explicar como funciona el sistema de tipos de~E
- desde otra perspectiva.
- \Espacio
- La mayor parte de los problemas que tiene la gente al programar en~E
- provienen de una visi\'on incorrecta del funcionamiento del sistema de
- tipos de~E\null{}. Por lo general se tiene una idea sobre el funcionamiento de
- los tipos que depende del lenguaje de programaci\'on usado con
- anterioridad y se intenta aplicarla a~E, lo que suele ser fatal, ya que~E
- es bastante diferente en lo que se refiere a tipos.
- \subsec El Sistema de Tipos.
- E es, en esencia, un lenguaje SIN-TIPOS\null{}. De hecho, las variables
- pueden tener un tipo, aunque s\'olo sirve para indicar la forma de hacer
- referencia a la variable cuando se usa como puntero. En practicamente
- todas las dem\'as construcciones del lenguaje las variables se tratan como
- si todas tuvieran el mismo tipo, un valor sin tipo de 32~bits.
- \noin En la pr\'actica esto significa que, por ejemplo, excepto expresiones
- que con los operadores |.|, |[]| y |++|, todos los operadores
- y funciones trabajan con valores de 32bits, independiente que si
- representan booleanos, enteros, reales o punteros a algo.
- \subsec Tipos punteros.
- En el sistema de tipos de E s\'olo hay 4 tipos, |PTR TO CHAR|, |PTR TO INT|,
- |PTR TO LONG| y |PTR TO |\<objeto>, donde \<objeto> es el nombre de un |OBJECT|o
- definido con anterioridad. Cuando una variable (o miembro de un objeto
- como veremos m\'as tarde) se declara de este tipo, significa que si la
- variable contiene un valor que es un puntero legal, esa es la forma de hacer
- referencia a ella.
- \subsec |LONG|, |ARRAY| etc.
- Todos los dem\'as tipos que podamos ver en una declaraci\'on |DEF| no son
- tipos reales, ya que no son m\'as que otras formas de escribir uno de los
- cuatro anteriores. Por ejemplo, |ARRAY OF |\<tipo> es otra forma de poner
- |PTR TO |\<tipo>, con la \'unica diferencia de que la primera recibe de forma
- autom\'atica la direcci\'on de un \'area de memoria en la pila que es
- suficientemente grande como para contener los datos para el n\'umero de
- elementos especificado entre corchetes.
- \noin Esta es una tabla que muestra todos los {\sl tipos} de E en t\'erminos de
- los cuatro b\'asicos:
- \ejemplos
- \qquad |ARRAY OF CHAR|, |ARRAY|, |STRING|, |LONG|&(equivale a)\quad |PTR TO CHAR|\cr
- \qquad |ARRAY OF INT|& (equivale a)\quad |PTR TO INT|\cr
- \qquad |ARRAY OF LONG|, |LIST|& (equivale a)\quad |PTR TO LONG|\cr
- \qquad |ARRAY OF |\<objeto>, \<objeto>& (equivale a)\quad |PTR TO |\<objeto>\cr
- \finsma
- \item{$-$} |LONG | son variables que no est\'an pensadas para ser usadas como puntero,
- por ejemplo, enteros. Su equivalencia con |PTR TO CHAR| es bastante
- l\'ogica, ya que ambos hablan conceptualemente de cosas que se miden en
- unidades de 1. (por ejemplo, |++| tiene el mismo efecto en ambos)
- \item{$-$} |LIST| y |STRING| son lo mismo que sus equivalentes en |ARRAY| respecto al
- hecho de que se incializan a un trozo de la pila, aunque su
- representaci\'on es algo m\'as compleja para facilitar la comprobaci\'on de
- rango en tiempo de ejecuci\'on (cuando se usan con funciones apropiadas).
- \item{$-$} un \<objeto> es equivalente a |[1]:ARRAY OF |\<objeto>. Ambos representan
- un |PTR TO |\<objeto> inicializado.
- \espacio
- Dentro de un |OBJECT| pueden aparecer estas mismas declaraciones, adem\'as
- de |CHAR| e |INT|, y no se permite declarar |LIST| ni |STRING|, ya que estos
- \'ultimos son objetos complejos en s\'{\i} mismos, y no pueden formar parte de
- un objeto.
- \subsec Referencia.
- Dado un puntero de alg\'un tipo,
- \item{``|[]|''} puede indicar otros elementos que est\'an ordenados secuencialmente a
- continuaci\'on del elemento al que el puntero est\'a apuntando en ese
- momento. Se\~nalar que esto permite \'{\i}ndices tanto positivos como
- negativos, y tampoco se hacen suposiciones sobre donde y cuantos
- elementos se han reservado en realidad.
- \item{``|++|''} hace que el puntero apunte al siguiente elemento en memoria, y |--|
- al anterior. Se\~nalar que estos operadores siempre act\'uan en el
- puntero, y nunca sobre el elemento al que apuntan.
- \item{``|.|''} funciona de forma similar a |[]|, s\'olo que indexa el puntero por
- nombre, es decir, el puntero debe ser un |PTR TO |\<objeto>.
- \espacio
- |[]| y |.| se pueden concatenar a un puntero |p| en cualquier secuencia,
- siempre que se sepa que el valor resultante anterior es de nuevo de tipo
- |PTR TO|.
- \noin No siempre es necesario escribir una referencia como en otros
- lenguajes. Por ejemplo, si |p| es un |ARRAY OF obj|, en lugar de escribir
- |p[indice].miembro| puedes escribir simplemente |p[indice]|, lo cual resulta
- en la direcci\'on de ese objeto. Esto tambi\'en explica porqu\'e |p[].miembro|
- equivale a |p.miembro|, ya que |p[]| es lo mismo que |p| cuando \'este
- apunta a un objeto.
- \subsec Sem\'atica de Referencia.
- Otro concepto relacionado con los tipos que hace a~E de alguna forma
- diferente de otros lenguajes ---y por tanto dificil de entender--- es su
- acento en la Sem\'antica de Referencia en vez de la Sem\'antica de Valor.
- Intentar\'e argumentar aqu\'{\i} los benef\'{\i}cios de la primera.
- \espacio
- Informalmente, Sem\'antica de Referencia significa que los objetos en un
- lenguaje (principalmente los que no son simples como los |LONG|) se
- representan mediante punteros, mientras que la Sem\'antica de Valor trata
- esos objetos como si fueran ellos mismos. Un ejemplo de lenguaje que
- s\'olo usa Sem\'antica de Valor es el BASIC, ejemplos de lenguajes que tienen
- las dos son lenguajes del tipo del C/C++ y del Pascal, y ejemplos de
- lenguajes con s\'olo Referencia son los nuevos lenguajes Orientados a
- Objetos, lenguajes funcionales como el LISP, y por supuesto~E.
- \noin El uso de Sem\'antica de Referencia no implica estar ocupado todo el
- tiempo con punteros, es m\'as, te preocupar\'as de ellos con mucha menos
- asiduidad que en el caso de lenguajes con sem\'antica mezclada o el caso
- con s\'olo valor, debido principalmente a que la mayor\'{\i}a de las estructuras
- de datos no triviales se reservan de forma din\'amica, lo cual implica
- punteros. El mejor ejemplo de esto es el LISP, en el que se programa
- fuertemente con punteros sin darse cuenta. En~E, uno se puede olvidar
- facilmente de que |STRING| es un puntero, debido a la facilidad con que se
- puede pasar entre funciones; en~C son necesarias a veces gran cantidad
- de~{\tt \&} cuando en el equivalente en~E no se necesitan, y el equivalente en
- Oberon de |bla('hola')| se parece a |bla(sys.ADR('hola'))| debido a que las
- cadenas no representan un puntero, si no un valor como un todo~\dots
- \endchapter\saltacap
- \beginchapter Cap\'{\i}tulo 9. Funciones\\Predefinidas
- \seccion Entrada/Salida.
- \proto{WriteF(cadenaformato,args,...)}
- \pproto{PrintF(cadenaformato,args,...)}
- Imprime una cadena (que puede contener c\'odigos de formato) en |stdout|.
- Pueden incorporar un n\'umero ilimitado de argumentos. Se\~nalar que, como
- las cadenas de formato se pueden crear din\'amicamente, no es posible
- cerciorarse de que el n\'umero de argumentos sea correcto.
- \Ejemplos
- Ejemplos:&|WriteF('!`Hola Mundo!\n') -> cadena con cambio de linea|\cr
- &|WriteF('a = \d \n',a) -> escribe: "a = 123", si a era 123|\cr
- \finsma
- NOTA: si, por ejemplo, |stdout=NIL| y tu programa fue iniciado desde el
- Workbench, |WriteF()| crear\'a una ventana de salida y pondr\'a el handle en
- |conout| y |stdout|. Esa ventana se cerrar\'a de forma autom\'atica al salir del
- programa despu\'es de que el usuario pulse \<{\rm return}>. |WriteF()| es la \'unica
- funci\'on que abre esta ventana, de modo que si quieres hacer E/S en
- |stdout|, y quieres estar seguro de que |stdout<>NIL|, haz un |WriteF('')|
- como primera instrucci\'on de tu programa para asegurar la salida. Si
- quieres abrir la ventana de consola por t\'{\i} mismo, debes hacerlo
- poniendo el handle de fichero resultante en las variables |stdout| y
- |conout|, ya que de esa forma la ventana se cerrar\'a de forma autom\'atica
- al finalizar el programa. Si deseas cerrar esa ventana de forma manual,
- aseg\'urate de volver a poner |conout| de nuevo a~|NIL| para indicar a~E que
- no hay una ventana de consola para cerrar.
- \espacio
- |PrintF()| es igual que |Write()|, s\'olo que utiliza E/S con buffers. Ambas
- retornan la longitud de la cadena que se acaba de imprimir.
- \proto{Out(handlefich,car)}
- \pproto{car:=Inp(handlefich)}
- Escriben o leen un s\'olo byte a/de alg\'un fichero o |stdout|. Si |car=-1|
- entonces se alcanz\'o el final del fichero (|EOF|), o sucedi\'o alg\'un error.
- |Out()| retorna el n\'umero de bytes que se escribieron en realidad (si es
- distinto de 1 entonces hubo un error).
- \proto{long:=FileLength(cadenanombre)}
- Determina la longitud del fichero que desees leer, y tambi\'en, si tal
- fichero existe (retorna |-1| si hubo un error, o el fichero no existe).
- \proto{ok:=ReadStr(handlefich,cadenae)}
- {\it (mejor mira en el partado sobre ``Cadenas y funciones de cadenas''.)}
- \proto{salant:=SetStdOut(nuevostdout)}
- \pproto{entant:=SetStdIn(nuevostdin)}
- Fija la variable de salida/entrada estandard |stdout|/|stdin|.
- Equivale a :
- \ejemplos
- &|salant:=stdout|\cr
- &|stdout:=newstdout|\cr
- \seccion Cadenas y funciones de cadenas.
- E tiene el tipo de datos |STRING|\null{}. Este es una cadena, que desde ahora
- llamaremos {\sl cadenaE}\nota{Estring.}, que se puede modificar y cambiar de
- tama\~no, al contrario que las {\it cadenas} normales, que es como nos
- referiremos aqu\'{\i} a cualquier secuencia terminada en cero. Las cadenasE
- son compatibles con las cadenas, aunque no en sentido inverso, de forma
- que si un argumento necesita una cadena, podemos pasar cualquiera de las
- dos. Si se necesita una cadenaE, no uses cadenas normales.
- \Ejemplos
- Ejemplos:&|DEF s[80]:STRING, n -> s es una cadenaE de longitud max. 80|\cr
- &|ReadStr(stdout,s) -> lee entrada desde la consola|\cr
- &|n:=Val(s) -> recoge un numero de la cadenaE|\cr
- &|-> etc.|\cr
- \finsma
- Se\~nalar que todas las funciones de cadenas manejan de forma correcta
- los casos en los que la cadena tiende a ser mayor que su longitud m\'axima:
- \ejemplos
- &|DEF s[5]:STRING|\cr
- &|StrAdd(s,'Esta cadena es mayor de 5 caracteres',ALL)|\cr
- &(|s| s\'olo contendr\'a |'Esta '|).\cr
- \finsma
- Las cadenas tambi\'en\nota{siempre debe comprobarse si el puntero que retorna
- esta funci\'on es |NIL|.} pueden reservarse din\'amicamente en la memoria del
- sistema con |String()|.
- \proto{s:=String(longmax)}
- \ejemplos
- &|DEF s[80]:STRING|\qquad equivale a\qquad |DEF s|\qquad seguido de |s:=String(80)|\cr
- \proto{bool:=StrCmp(cadena,cadena,long=ALL)}
- Compara dos cadenas. |long|\nota{|long| es un argumento por omisi\'on.} debe ser el n\'umero de caracteres a comparar,
- o |ALL| si queremos comparar la totalidad de la cadena. Retorna
- |TRUE| o |FALSE|.
- \proto{StrCopy(cadenaE,cadena,long=ALL)}
- Copia |cadena| en |cadenaE|\null{}. Si |long=ALL| copiar\'a toda la cadena.
- Retorna la |cadenaE|
- \proto{StrAdd(cadenaE,cadena,long=ALL)}
- Igual que |StrCopy()|, s\'olo que ahora la cadena se concatena al final.
- Retorna la |cadenaE|.
- \proto{long:=StrLen(cadena)}
- Calcula la longitud de cualquier cadena terminada en cero.
- \proto{long:=EstrLen(cadenaE)}
- Retorna la longitud de una |cadenaE|.
- \proto{max:=StrMax(cadenaE)}
- Retorna la longitud m\'axima de una |cadenaE|.
- \proto{StringF(cadenaE,cadenafmt,args,...)}
- Como |WriteF()|, pero ahora la salida va a |cadenaE| en vez de |stdout|.
- Retorna la |cadenaE|, y su longitud como segundo valor de retorno.
- \ejemplos
- &|StringF(s,'resultado: \d\n',123)|\qquad en |s| tendremos ``|resultado: 123\n|''\cr
- \proto{RightStr(cadenaE,cadenaE,n)}
- Rellena la primera |cadenaE| con los \'ultimos |n| caracteres de la segunda.
- Retorna la |cadenaE|.
- \proto{MidStr(cadenaE,cadena,pos,long=ALL)}
- Copia |long| caracteres (todos si |long=ALL|) desde la posici\'on |pos| de
- |cadena| a |cadenaE|\null{}. Retorna la |cadenaE|.
- \Espacio
- {\bf Nota importante}: en todas las funciones relacionadas con cadenas en las que
- se usa una posici\'on de cadena, el primer caracter de la cadena est\'a en la
- posici\'on 0, y no 1 como es com\'un en algunos lenguajes como el BASIC.
- \proto{valor,leidos:=Val(cadena,leidos=NIL)}
- Extrae el valor entero que representa la secuencia de caracteres \ASCII/
- de la cadena. No se tienen en cuenta los espacios\b/tabuladores,~\dots\enspace que le
- precedan. De esta forma tambi\'en se pueden leer n\'umeros hexadecimales
- (|1234567890ABCDEFabcdef|) y binarios (|01|) si van precedidos de |$| o |%|
- respectivamente. Un menos |-| puede indicar un entero negativo. |Val()|
- tambi\'en retorna el n\'umero de caracteres leidos como segundo argumento, el
- cual debe pasarse por referencia, o se puede recibir como segundo valor
- de retorno. Si |leidos| es 0 (|valor| ser\'a 0 tambi\'en) entonces la cadena
- no conten\'{\i}a un entero, o el valor era muy grande para ponerlo en 32~bits.
- |leidos| puede ser |NIL|.
- \espacio
- Ejemplos de cadenas que se analizan correctamente:
- \ejemplos
- &|'-12345', '%10101010', ' -$ABcd12'|\cr
- Estos otros retornar\'an con |valor| y |leidos| igual a 0:
- \ejemplos
- &|'', 'hello!'|\cr
- \proto{posbusc:=InStr(cadena1,cadena2,posinicial=0)}
- Busca en |cadena1| la aparici\'on de |cadena2|, probablemente partiendo de
- una posici\'on diferente de~0. Retorna la posici\'on en la que se hall\'o la
- subcadena, o |-1| en otro caso.
- \proto{nuevadircadena:=TrimStr(cadena)}
- Retorna la {\sl direcci\'on} del primer caracter de la cadena que no sea un
- espacio, tabulador, etc~\dots
- \proto{UpperStr(cadena)}
- \pproto{LowerStr(cadena)}
- Cambia la cadena de mayusculas o a min\'usculas. Retorna una cadena.
- \espacio
- {\bf Nota importante}: estas funciones cambian el contenido de la |cadena|, por lo
- que s\'olo pueden usarse con |cadenasE|, o cadenas que formen parte de los
- datos de tu programa. Esto quiere decir concretamente, que si obtienes
- la direcci\'on de una cadena con una llamada a una funci\'on del sistema,
- primero deber\'as hacer |StrCopy()| a una cadena de tu programa, para
- poder usar las funciones.
- \proto{ok:=ReadStr(handlefich,cadenaE)}
- Lee una cadena (acabada en \ASCII/ 10) de cualquier fichero o de |stdout|.
- |ok| contendr\'a |-1| si ocurri\'o un error, o se alcanz\'o el |EOF|.
- \noin Es importante que sepas que el contenido de la cadena leida hasta ese
- momento sigue siendo v\'alido. Se\~nalar tambi\'en que, al igual que |Inp()|,
- |Out()|,~\dots\enspace esta funci\'on utiliza un estilo de |E/S| sin buffers, y por lo
- tanto puede ser lenta. La funci\'on de la dos.library |FGets()| es una buena
- alternativa.
- \proto{SetStr(cadenaE,nuevalong)}
- Cambia manualmente la longitud de la cadena. S\'olo es \'util cuando
- pones datos en una cadenaE mediane una funci\'on no espec\'{\i}fica de
- cadenasE y quieres seguir utilizandola como cadenaE\null{}. Por ejemplo,
- despu\'es de usar una funci\'on que simplemente pone una cadena terminada
- en cero en la direcci\'on de la cadenaE, entonces puedes usar
- |SetStr(micade,StrLen(micade))| para volverla manipulable de nuevo. Si la
- cadena es demasiado larga, |SetStr()| no har\'a nada (aunque eso debe
- evitarse siempre).
- \proto{AstrCopy(cadena1,cadena2,tama\~no)}
- {\it Array String Copy} copia |cadena2| en el \'area de memoria denotado por
- |cadena1|. |cadena1| no suele ser una cadenaE, sino un |ARRAY|\null{}. {\tt tama\~no} es el
- n\'umero total de caracteres que puede contener |cadena1|, por ej., si es 5 y
- |cadena2='holamundo'|, |cadena1| tendr\'a entonces |'hola'| + terminaci\'on en 0.
- \proto{orden:=OstrCmp(cadena1,cadena2,max=ALL)}
- {\it Ordered String Compare} retorna |1| si |cadena2>cadena1|, |0| si son
- iguales y |-1| si es menor. S\'olo se camparan |max| caracteres.
- \espacio
- Puede que te sea interesante que heches un vistazo al apartado sobre
- ``Enlace de cadenas''
- \seccion Listas y funciones de listas.
- Las listas son como las cadenas, la \'unica diferencia es que est\'an
- formadas por |LONG|s en lugar de |CHAR|s. Tambi\'en pueden reservarse de forma
- global, local o din\'amica.
- \begintt
- DEF milista[100]:LIST -> local o global.
- DEF a
- a:=List(10) -> dinamica. En este caso, 'a' puede ser NIL.
- \endtt
- De la misma forma que las cadenas se pueden representar con constantes
- en expresiones, las listas tienen equivalentes constantes:
- \ejemplos
- &|[1,2,3,4]|\cr
- el valor de tales expresiones es un puntero a una lista inicializada. Una
- caracter\'{\i}stica que tienen estas listas es que pueden tener partes
- din\'amicas, es decir, partes que se completan en tiempo de ejecuci\'on:
- \ejemplos
- &|a:=3|\cr
- &|[1,2,a,4]|\cr
- incluso pueden tener otro tipo que no sea el |LONG| por omisi\'on, como:
- \ejemplos
- &|[1,2,3]:INT|\cr
- &|[65,66,67,0]:CHAR -> equivalente a 'ABC'|\cr
- &|['topaz.font',8,0,0]:textattr|\cr
- &|OpenScreenTagList(NIL,[SA_TITLE,'MiPantalla',TAG_DONE])|\cr
- \finsma
- Como se ve en los ejemplos anteriores, las listas son extremadamente
- \'utiles con funciones del sistema: son compatibles con un |ARRAY OF LONG|,
- y las de objetos con tipos se pueden utilizar en cualquier lugar que
- necesite una estructura, o arreglo de ellas. Las funciones de Taglist y
- de n\'umero variable de argumentos se pueden utilizar de esta forma.
- Sin embargo las funciones de listas s\'olo funcionan con listas de |LONG|,
- las listas con tipos s\'olo son convenientes para la construcci\'on de
- estructuras de datos complejas y expresiones.
- \espacio
- Al igual que las cadenas, las listas mantienen cierta jeraqu\'{\i}a:
- \ejemplos
- &listas var. |->| listas const. |->| arreglos de long/puntero a long\cr
- cuando una funci\'on necesita un arreglo de |LONG|s puedes usar tranquilamente
- una lista como argumento, pero si la funci\'on necesita una lista
- variable, o una lista constante, entonces no servir\'a un arreglo de LONGs.
- \espacio
- Es importante entender el poder de las listas, y en particular las
- listas con tipo: \'estas pueden evitar una buena cantidad de problemas en
- la construcci\'on de pr\'acticamente cualquier estructura de datos. Intenta
- usar las listas en tus propios programas, y observa la funci\'on que tienen
- en los programas de ejemplo.
- \espacio
- \Ejemplos
- Resumen:\cr
- \qquad\qquad|[|\<elem>,\<e>,...| ]| &lista inmediata (|LONG|s, con funcs. de listas)\cr
- \qquad\qquad|[|\<elem>,\<e>,...| ]:|\<tipo>&lista con tipos (para crear estruct. de datos)\cr
- Si \<tipo> en un tipo simple como |INT| o |CHAR|, lo que obtienes es un
- equivalente inicializado de un |ARRAY OF |\<tipo>, si \<tipo> es un nombre de
- objeto, estar\'as construyendo objetos inicializados, o |ARRAY OF |\<objeto>,
- dependiendo de la longitud de la lista.
- \espacio
- Si escribes\quad |[1,2,3]:INT|\quad crear\'as una estructura de 6~bytes, de
- 3~valores de 16~bits para ser m\'as preciso. El valor de esta expresi\'on es,
- entonces, un puntero a ese \'area de memoria. Lo mismo ocurre si, por
- ejemplo, tienes un objeto como este:
- \ejemplos
- &|OBJECT miobjeto|\cr
- &\qquad|a:LONG, b:CHAR, c:INT|\cr
- &|ENDOBJECT|\cr
- escribir\quad |[1,2,3]:miobjeto|\quad implicar\'a la creaci\'on de una estructura de
- datos en memoria de 8~bytes, siendo los cuatro primeros bytes un |LONG| de
- valor~1, el siguiente byte un |CHAR| de valor~2, luego un byte relleno, y
- los dos \'ultimos un |INT| (2bytes) de valor~3. Tambi\'en podr\'{\i}as escribir:
- \ejemplos
- &|[1,2,3,4,5,6,7,8,9]:myobject|\cr
- y estar\'{\i}as creando un |ARRAY OF miobjeto| de tama\~no~3. F\'{\i}jate que tales
- listas no tienen porqu\'e ser completas (con 3,6,9,\dots\enspace elementos), puedes
- crear objetos parciales con listas de cualquier tama\~no.
- \espacio
- Un \'ultimo apunte sobre el tama\~no de los datos: en el Amiga puedes
- depender del hecho de que una estructura como |miobjeto| tiene un tama\~no
- de 8~bytes, y que tiene un byte de relleno para obtener alineaci\'on de
- palabras (16~bit). Sin embargo, es bastante probable que un compilador de~E
- para arquitecturas |80x86| no usar\'{\i}a el byte de relleno y crear\'{\i}a una
- estructura de 7~bytes, y que un compilador de~E para una arquitectura
- |sun-sparc|, si no me equivoco, intentar\'{\i}a alinear los datos a palabras
- dobles (32~bits), creando una estructura de~10 o 12~bytes. Algunos
- microprocesadores (son raros, pero existen) incluso usar\'{\i}an (|36:18:9|)
- como n\'umero de bits para sus tipos (|LONG:INT:CHAR|), en lugar de los
- (|32:16:8|) a los que estamos habituados. Con esto quiero decir que no
- hagas muchas suposiciones sobre la estructura de los |OBJECT|os y las
- |LIST|as si quieres escribir c\'odigo que tenga alguna oportunidad de ser
- portable y que no dependa de efectos laterales.
- \proto{ListCopy(listavar,lista,num=ALL)}
- Copia |num| elementos de |lista| a |listvar|. Retorna |listavar|.
- \Ejemplos
- Ejemplo:&|DEF milista[10]:LIST|\cr
- &|ListCopy(milista,[1,2,3,4,5],ALL)|\cr
- \proto{ListAdd(listavar,lista,num=ALL)}
- Copia |num| elementos de |lista| en la cola de |listavar|. Retorna |listavar|.
- \proto{ListCmp(lista,lista,num=ALL)}
- Compara dos listas, o una parte de ellas.
- \proto{long:=ListLen(lista)}
- Retorna la longitud de |lista|, ej: |ListLen([a,b,c])| retornar\'{\i}a 3.
- \proto{max:=ListMax(listavar)}
- Retorna la longitud m\'axima posible de |listavar|.
- \proto{valor:=ListItem(lista,indice)}
- Opera como\quad |value:=list[indice]|\quad con la diferencia de que |lista|
- puede ser un valor constante en vez de un puntero. Esto es bastante \'util
- en situaciones como la siguiente en la que queremos usar una lista de
- valores directamente:
- \ejemplos
- &|WriteF(ListItem(['!`vale!','!`sin mem!','!`no fichero!'],error))|\cr
- que imprime un mensaje de error dependiendo de |error|. Equivale a:
- \ejemplos
- &|DEF temp:PTR TO LONG|\cr
- &|temp:=['!`vale!','!`sin mem!','!`no fichero!']|\cr
- &|WriteF(temp[error])|\cr
- \finsma
- \proto{SetList(listavar,nuevalong)}
- Cambia la longitud de la lista de forma manual. S\'olo ser\'a \'util cuando
- leas informaci\'on en la lista con una funci\'on que no sea espec\'{\i}fica para
- listas, y quieres seguir utilizandola como una lista de verdad.
- \Espacio
- Puede que te resulte interesante, mirar las funciones de listas con expresiones
- entrecomilladas as\'{\i} como las funciones de enlace de listas.
- \seccion Intuition.
- \proto{ptrv:=OpenW(x,y,ancho,alto,IDCMP,wflags,tit,pant,sflags,gads,tagl=NIL)}
- Crea una ventana donde |wflags| son los flags de caracter\'{\i}sticas de la
- ventana (como |BACKDROP|, |SIMPLEREFRESH|,~\dots, generalmente |$F|) y |sflags| son
- los que indican el tipo de pantalla en la que se abrir\'a la ventana (1=wb,
- 15=propia). Si |sflags=15| entonces es necesario que |pant| sea un puntero v\'alido,
- en otro caso sirve |NIL|\null{}. |gads| puede apuntar a una
- estrutura |glist| que puedes crear f\'acilmente con la funci\'on |Gadget()|, en
- otro caso |NIL|.
- \proto{CloseW(ptrv)}
- Cierra la ventana de nuevo. La \'unica diferencia con |CloseWindow()| es
- que acepta punteros |NIL|, y que vuelve a poner |stdrast| a |NIL|.
- \proto{ptrp:=OpenS(ancho,alto,planos,sflags,titulo,taglist=NIL)}
- Crea una pantalla propia. |planos|=n\'umero de bitplanes (|1-6|, \'o |1-8| en AGA).
- \proto{CloseS(ptrp)}
- Igual que |CloseW()|, s\'olo que para pantallas.
- \proto{buffersig:=Gadget(buffer,listag,id,flags,x,y,ancho,cadena)}
- \pproto{{\it Atenci\'on: esta funci\'on est\'a un poco anticuada.}}
- Esta funci\'on crea una lista de gadgets, los cuales se pueden luego
- incluir en t\'u ventana pas\'andola como argumento a |OpenW()|, o
- posteriormente con funciones de Intuition como |AddGlist()|.
- \noin |buffer| es por lo general un |ARRAY| de al menos |GADGETSIZE| bytes para
- mantener todas las estructuras asociadas con un gadget, |id| es n\'umero
- identificador que nos ayudar\'a a recordar el gadget pulsado cuando llegue
- un IntuiMessage. |flags| puede ser: 0=gadget normal, 1=gadget booleano,
- 3=gadget booleano seleccionado. |ancho| es el ancho en pixels, y debe
- ser lo suficientemente grande como para acoger |cadena|, la cual estar\'a
- centrada autom\'aticamente. |listag| debe ser |NIL| para el primer gadget, y
- varlistag para todos los dem\'as, para que~E pueda enlazar los gadgets.
- \noin La funci\'on retorna un puntero al siguente buffer (|=buffer+GADGETSIZE|).
- \noin Ejemplo para tres gadgets:
- \begintt
- CONST MAXGADGETS=GADGETSIZE*3
- DEF buf[MAXGADGETS]:ARRAY, sigui, ptrv
- sigui:=Gadget(buf,NIL,1,0,10,20,80,'bla') -> el 1er gadget
- sigui:=Gadget(sigui,buf,... )
- sigui:=Gadget(sigui,buf,... ) -> enlaza gadgets
- ptrv:=OpenW( ...,buf)
- \endtt
- \proto{codigo:=Mouse()}
- Retorna el estado actual de los 2 o 3 botones del rat\'on; izqdo=1,
- dcho=2 y central=4. Si, por ejemplo, codigo=3 querr\'a decir que se
- pulsaron los botones izquierdo y derecho a la vez.
- \espacio
- {\bf Importante}: Esta no es una funci\'on real de Intuition, si quieres conocer los
- eventos del rat\'on de una forma correcta, tendr\'as que analizar los
- |IntuiMessage| que reciba tu ventana. Esta es la \'unica funci\'on de~E que
- utiliza el hardware directamente, y por tanto s\'olo es aconsejable para
- programas de tipo demo, o para pruebas. ({\bf No uses esta funcion en
- programas que se supone van a funcionar bajo el SO}).
- \proto{bool:=LeftMouse(ven)}
- \pproto{WaitLeftMouse(ven)}
- Alternativa de Intuition a |Mouse()|, comprueban la pulsaci\'on del rat\'on.
- \proto{x:=MouseX(ven)}
- \pproto{y:=MouseY(ven)}
- Permite leer la posici\'on del rat\'on. Coordenadas relativas a la ventana |ven|.
- \proto{clase:=WaitIMessage(ventana)}
- Esta funci\'on hace m\'as f\'acil la espera de un evento de ventana. Espera
- la llegada de un |IntuiMessage| y retorna la clase del evento. Guarda otros
- datos como |codigo| y |calificadores| en variables globales privadas, que
- pueden leerse con las siguientes funciones. |WaitIMessage()| equivale al
- siguiente fragmento de c\'odigo:
- \begintt
- PROC waitimessage( ven:PTR TO window )
- DEF puerto,mens:PTR TO intuimessage,clase,codigo,calif,diri
- puerto:=ven.userport
- IF (mens:=GetMsg(puerto)) = NIL
- REPEAT
- WaitPort(puerto)
- UNTIL (mens:=GetMsg(puerto)) <> NIL
- ENDIF
- clase:=mens.class
- codigo:=mens.code /* almacenado internamente */
- calif:=mens.qualifier
- diri:=mens.iaddress
- ReplyMsg(mens)
- ENDPROC clase
- \endtt
- como puedes ver, recoge exactamente un mensage, y no se olvida de
- m\'ultiples mensajes que llegan en el mismo evento, si se llama m\'as de una
- vez. Digamos, por ejemplo, que has abierto una ventana que muestra algo
- y simplemente espera a que la cierres (s\'olo indicaste |IDCMP_CLOSEWINDOW|):
- \ejemplos
- &|WaitIMessage(miventana)|\cr
- o puedes tener un programa que espere por m\'as tipos de eventos, que
- controlar\'{\i}as en un bucle, y finaliza con un evento |CLOSEWINDOW|:
- \ejemplos
- &|WHILE (clase:=WaitIMessage(ven))<>IDCMP_CLOSEWINDOW|\cr
- &| /* trata otras clases */|\cr
- &|ENDWHILE|\cr
- \finsma
- \proto{codigo:=MsgCode()}
- \pproto{calif:=MsgQualifier()}
- \pproto{diri:=MsgIaddr()}
- Proporcionan las variables globales privadas mencionadas antes. Los
- valores que retornan son los definidos durante la llamada a
- |WaitIMessage()| m\'as reciente.
- \Ejemplos
- Ejemplo:&|IF clase:=IDCMP_GADGETUP|\cr
- &| migadget:=MsgIaddr()|\cr
- &| IF migadget.userdata=1 THEN ... -> el usuario pulso gadget 1|\cr
- &|ENDIF|\cr
- \seccion Gr\'aficos.
- Todas las funciones gr\'aficas de apoyo que requieren expl\'{\i}citamente
- un rastport utilizan la variable de sistema |stdrast|, definida
- autom\'aticamente en la \'ultima llamada a |OpenW()| o |OpenS()|, y que toma el
- valor |NIL| con |CloseW()| y |CloseS()|. Se puede llamar a estas dos \'ultimas
- funciones cuando |stdrast| a\'un es |NIL|\null{}. Se le puede dar un valor a
- |stdrast| manualmente con |SetStdRast()| o |stdrast:=mirastport|.
- \proto{Plot(x,y,color=1)}
- Dibuja un s\'olo punto en tu pantalla/ventana con uno de los colores
- disponibles. El n\'umero del color va desde |0...31|, o~|0...255| bajo AGA.
- \proto{Line(x1,y1,x2,y2,color=1)}
- Dibuja una l\'{\i}nea.
- \proto{Box(x1,y1,x2,y2,color=1)}
- Dibuja un rect\'angulo o caja.
- \proto{Colour(dibujo,fondo=0)}
- Fija los colores\nota{las funciones que necesitan un {\it color} cambian el |Apen| de |stdrast|.}
- para todas las funciones gr\'aficas (de la librer\'{\i}a)
- que necesiten un color como argumento. Este es el {\sl registro} del color
- (por ejemplo, de |0...31|) y no el {\sl valor} del color.
- \proto{TextF(x,y,cadenaformato,args,...)}
- Exactamente igual que |WriteF()|, s\'olo que escribe en alg\'un (x,y) de tu
- |stdrast|, en lugar de hacerlo a |stdout|. Retorna la longitud de la cadena
- resultante.
- \proto{rastant:=SetStdRast(rastnuevo)}
- Cambia el rastport de salida de las funciones gr\'aficas de E.
- \proto{SetTopaz(tama\~no=8)}
- Te permite fijar la fuente del rastport |stdrast| a topaz, simplemente
- para asegurarte de que alguna fuente propia no desfigure la composici\'on
- de la ventana. Por supuesto, |tama\~no| puede ser 8 o 9. Est\'a para usarse
- como \'ultimo recurso si no permites sensibilidad a fuentes.
- \proto{SetColour(pantalla,regcolor,r,g,b)}
- Fija el registro de color (|0...255|) de la pantalla a cierto valor {\sc RGB}.
- Cada valor de {\sc RGB} puede oscilar entre |0...255|, es decir, color de 24~bits.
- Esta funci\'on reescalar\'a el color de forma autom\'atica si no se dispone de
- un modo AGA, utilizando la funci\'on apropiada.
- \seccion Sistema.
- \vskip-\medskipamount
- \proto{bool:=KickVersion(vers)}
- Retornar\'a |TRUE| si el KickStart de la m\'aquina en que est\'a corriendo tu
- programa es igual o superior a |vers|, en otro caso |FALSE|.
- \proto{mem:=New(n)}
- Esto crea din\'amicamente un arreglo (\'area de memoria, si lo prefieres)
- de |n|~bytes. Se diferencia de |AllocMem()| en que se llama de forma autom\'atica
- con flags |$10000| (es decir, memoria inicializada a zero de cualquier
- tipo), y en que no es necesario llamar a |Dispose()|, ya que est\'a enlazada
- a una lista de memoria {\sl liberada autom\'aticamente} al finalizar el programa.
- \proto{mem:=NewR(n)}
- Igual que |New()|, solo que ahora alcanza la excepci\'on |"MEM"| de forma
- autom\'atica en lugar de retornar cuando no hay suficiente memoria.
- \proto{mem:=NewM(n,flags)}
- Igual que |NewR()|, y adem\'as permite especificar flags (|MEMF_CHIP| etc.)
- \proto{Dispose(mem)}
- Libera memoria reservada con |New()|. S\'olo es necesaria cuando quieras liberar memoria
- de forma expl\'{\i}cita {\it durante} el programa, ya que, al final del programa se
- libera toda la memoria.
- \proto{CleanUp(valorret=0)}
- Finaliza el programa en cualquier punto. Substituye al |Exit()|
- de DOS: !`nunca uses |Exit()|!, utiliza |CleanUp()| en su lugar, ya que
- libera la memoria, cierra las librerias correctamente,~\dots \enspace |valorret| se
- da al DOS como c\'odigo de retorno. S\'olo se necesita |CleanUp()| cuando
- hay que finalizar el programa en un punto diferente al |ENDPROC| de |main()|.
- \proto{cantidad:=FreeStack()}
- Retorna la cantidad de espacio libre que hay en la pila. Que debe ser
- siempre 1000 o superior. No debes preocuparte de tal cantidad mientras
- no utilice recursiones profundas.
- \proto{bool:=CtrlC()}
- Retorna |TRUE| si se ha pulsado |Ctrl-C| desde la \'ultima comprobaci\'on, en
- otro caso |FALSE|\null{}. S\'olo funciona en programas que se est\'an ejecutando en
- una consola, es decir, programas de |CLI|.
- \noin Ejemplo de uso de las tres \'ultimas funciones:
- \begintt
- -> calcular el factorial de un argumento de la linea de comandos
- OPT STACK=100000
- PROC main()
- DEF num, r
- num:=Val(arg,{r})
- IF r=0
- WriteF('args erroneos.\n')
- ELSE
- WriteF('resultado: \d\n',fac(num))
- ENDIF
- ENDPROC
- PROC fac(n)
- DEF r
- IF FreeStack()<1000 OR CtrlC() THEN CleanUp(5) -> test extra
- IF n=1 THEN r:=1 ELSE r:=fac(n-1)*n
- ENDPROC r
- \endtt
- por supuesto, es dif\'{\i}cil que esta recursi\'on acabe con el espacio de la
- pila, y si lo hace, el programa se detiene con |FreStack()| tan r\'apido que
- no te dar\'a tiempo a pulsar |Ctrl-C|, pero aqu\'{\i} lo que cuenta es la idea.
- Una definici\'on de |fac(n)| menos segura ser\'{\i}a:
- \ejemplos
- &|PROC fac(n) IS IF n=1 THEN 1 ELSE fac(n-1)*n|\cr
- \proto{mem:=FastNew(tama\~no)}
- \pproto{FastDispose(mem,tama\~no)}
- \pproto{FastDisposeList(lista)}
- |FastNew()| y |FastDispose()| substituyen a |NewR(size)| y |Dispose(ptr)| (|NEW|
- y |END| los utilizan). Esto es lo que tienen en com\'un:
- \item{$-$} pueden lanzar excepciones |"NEW"|.
- \item{$-$} la memoria siempre se inicializa a cero.
- \item{$-$} liberaci\'on autom\'atica al final del programa.
- \espacio
- aunque deben se\~nalarse las siguientes diferencias positivas\nota{con objetos
- |<=256| bytes, con mayores se usa |NewR()| y |Dispose()|} :
- \item{$-$} son entre 10 y 50 veces m\'as r\'apidas (!)
- \item{$-$} usan algo menos de memoria para objetos peque\~nos.
- \item{$-$} no fragmentan la memoria.
- \espacio
- y negativas :
- \item{$-$} no liberan la memoria, la reciclan.
- \item{$-$} |FastDispose()| necesita tama\~no exacto de la reserva. |END| tambi\'en.
- \espacio
- Para liberar listas reservadas con |NEW| se necesita utilizar la funci\'on
- |FastDisposeList()|. Dado que las listas tienen longitud, no hace falta el
- par\'ametro de tama\~no.
- \seccion Matem\'aticas y otras.
- \proto{a:=And(b,c)}
- \pproto{a:=Or(b,c)}
- \pproto{a:=Not(b)}
- \pproto{a:=Eor(b,c)}
- Estas funcionan con las operaciones usuales, tanto booleanas como
- aritm\'eticas. Se\~nalar que existen operadores para |And()| y |Or()|.
- \proto{a:=Mul(b,c)}
- \pproto{a:=Div(a,b)}
- Realizan la misma operaci\'on que los operadores |*| y |/|, aunque con
- 32~bits completos. Por razones de velocidad, las operaciones normales
- son |16bit*16bit=32bit| y |32bit/16bit=16bit|. Suficiente para pr\'acticamente
- todos los c\'alculos, y si no lo es, puedes usar |Mul()| y |Div()|\nota{en este
- caso, |a| se divide entre |b|, y no |b| entre |a|.}.
- \proto{bool:=Odd(x)}
- \pproto{bool:=Even(x)}
- \espacio
- Retorna |TRUE| o |FALSE| si la expresi\'on es impar (|Odd()|) o par (|Even()|).
- \proto{Min(a,b)}
- \pproto{Max(a,b)}
- Computan el m\'{\i}nimo y m\'aximo de dos enteros.
- \proto{numaleat:=Rnd(max)}
- \pproto{semilla:=RndQ(semilla)}
- |Rnd()| computa un n\'umero aleatorio a partir de una semilla interna,
- oscilando entre |0...max-1|. Por ejemplo, |Rnd(1000)| retorna un entero entre
- |0...999|. Para inicializar la semilla interna, llama a |Rnd()| con un valor
- negativo; el |Abs()| de ese valor ser\'a la semilla inicial.
- \noin |RndQ()| computa un n\'umero aleatorio m\'as r\'apido que |Rnd()|, aunque
- retorna n\'umeros en todo el rango de los 32~bits. Usa el resultado como
- semilla para la siguiente llamada, y como semilla inicial utiliza
- cualquier valor grande, como |$A6F87EC1|.
- \proto{valorabs:=Abs(valor)}
- Computa el valor absoluto.
- \proto{s:=Sign(v)}
- Computa el signo de |v|, es decir, retorna |-1|, |0| o |1|.
- \proto{a,b:=Mod(c,d)}
- Divide |c| (32bit) entre |d| (16bit) y retorna el m\'odulo |a| (16bit) y
- opcionalmente el resultado |b| (16bit) de la divisi\'on. |Mod()| retornar\'a
- resultados err\'oneos si se excede el l\'{\i}mite de los 16~bits.
- \proto{x:=Shl(y,num)}
- \pproto{x:=Shr(y,num)}
- Desplaza |y| |num| bits a la izquierda o a la derecha (bits nuevos a 0).
- \proto{a:=Long(dir)}
- \pproto{a:=Int(dir)}
- \pproto{a:=Char(dir)}
- Mira en una direcci\'on determinada de la memoria y retorna el valor
- encontrado. Funcionan con valores de~32, 16 y~8~bits respectivamente.
- Se\~nalar que el compilador {\bf no} comprueba si |dir| es una direcci\'on
- v\'alida. Estas funciones est\'an disponibles para que se utilicen s\'olo en
- los casos en los que la lectura y escritura de memoria mediante
- |PTR TO |\<type> har\'{\i}a el programa m\'as complejo o menos eficiente. Es
- {\bf desaconsejable} el uso de estas funciones.
- \proto{PutLong(dir,a)}
- \pproto{PutInt(dir,a)}
- \pproto{PutChar(dir,a)}
- Escribe el valor |a| en memoria. Mira |Long()|, |Int()| y |Char()|.
- \proto{y:=Bounds(x,a,b)}
- Asegura que |x| se encuentre entre |a| y |b|, y lo ajusta de forma acorde si
- es necesario. Equivale a:
- \ejemplos
- &|y:=IF x<a THEN a ELSE IF x>b THEN b ELSE x|\cr
- \seccion Enlace de cadenas y listas.
- E proporciona un conjunto de funciones\nota{estas funciones de cadenas/listas
- no tienen nada que ver con las listas-E o las listas Celdas-Lisp} que
- permite la creaci\'on de
- listas enlazadas con los tipos de datos |STRING| y |LIST|, o cadenas y listas
- creadas con |String()| y |List()| respectivamente. Como ya debes saber, las
- cadenas y las listas, tipos de datos complejos, son punteros a sus
- respectivos datos, y tienen campos extra en offsets negativos de ese
- puntero, que indican su longitud y longitud m\'axima actuales. Los offsets
- de los campos son privados (|PRIVATE|). Todos los tipos de datos complejos
- tienen, adem\'as de esos dos, un campo |next| (siguiente), inicializado a
- |NIL| por omisi\'on, y que se puede usar para construir listas o cadenas
- enlazadas, por ejemplo. Desde ahora, usar\'e |complejo| para denotar un
- puntero a |STRING| o |LIST|, y |cola| para denotar otro puntero de ese tipo,
- o que ya tenga otras cadenas enlazadas a \'el. |cola| tambi\'en puede ser un
- puntero |NIL|, indicando el final de una lista enlazada. Se pueden usar
- las siguiente funciones:
- \proto{complejo:=Link(complejo,cola)}
- Pone |cola| en el |next| de |complejo|. Retorna |complejo| de nuevo.
- \Ejemplos
- Ejemplo:&|DEF s[10]:STRING, t[10]:STRING|\cr
- &|Link(s,t)|\cr
- &crear\'a una lista enlazada como: \quad |s --> t --> NIL|\cr
- \proto{cola:=Next(complejo)}
- Lee el campo |next| de |complejo|. Puede ser |NIL|, o una lista enlzada
- completa. |Next(NIL)| resultar\'a en |NIL|, luego es seguro llamar a |Next()|
- cuando no est\'as seguro si estas al final de la lista enlazada o no.
- \proto{cola:=Forward(complejo,num)}
- Como |Next()|, s\'olo que adelanta |num| enlaces en lugar de uno, es
- decir |Forward(c,1)| equivale a |Next(c)|. Puedes utilizar |Forward()| con un
- |num| grande de forma segura, |Forward()| se detendr\'a si encuentra |NIL|
- mientras recorre los enlaces, y retornar\'a |NIL| en ese caso.
- \proto{DisposeLink(complejo)}
- Como |Dispose()|, con dos diferencias: s\'olo sirve para cadenas y listas
- reservadas con |String()| o |List()|, adem\'as liberar\'a el resto de |complejo|
- autom\'aticamente. Se\~nalar tambi\'en que se puede usar con listas enlazadas
- grandes que contengan tanto cadenas reservadas con |String()| como algunas
- reservadas localmente o globalmente con |STRING|.
- \espacio
- Puede que te interese mirar\enspace |Src/Utils/D.e|\enspace para ver un buen
- ejemplo de como se puede hacer buen uso de listas o cadenas enlazadas
- en programas reales.
- \seccion Celdas-Lisp y funciones de celdas.
- Vaya. Correcto. Pensabas que el LISP era divertido, entonces prueba E.\nota{o la
- historia de por qu\'e E es un LISP mejor que el propio LISP |:-)|}
- \espacio
- A partir de la versi\'on v3, E tiene el tipo de datos celda, casi
- id\'entico a las celdas del lenguaje LISP\null{}. M\'as t\'ecnicamente, E~tiene\nota{
- ``Celdas-Lisp con recogida de residuos con marcas conservadoras e intercambio''}:
- \ejemplos
- &``Conservative Mark and Sweep Garbage-Collected Lisp-Cells''\cr
- \espacio
- B\'asicamente, implica el ser capaz de reservar celdas-LISP, las cuales
- son pares de valores:
- \ejemplos
- &|x:=<a|\|{}|b>|\cr
- \finsma
- Lo cual se parece mucho a |NEW [a,b]:LONG|, s\'olo que ahora~E liberar\'a
- los 8~bytes en cuesti\'on por s\'{\i} s\'olo cuando se encuentre que necesita
- memoria, y no haya punteros apuntando a la celda. En la pr\'actica esto
- significa que puedes tener funciones que crean celdas temporales sin
- preocuparse de liberarlas. Y, cualquier\nota{este texto no explica
- detenidamente como aprovechar las celdas por completo, ya que se han escrito
- docenas de libros a ese respecto.} programador de LISP ser\'{\i}a capaz
- de explicarte que con celdas puedes construir cualquier tipo de estrutura
- de datos (m\'as notablemente \'arboles y listas).
- \espacio
- La selecci\'on de los valores se puede realizar usando |Car(x)| y |Cdr(x)|,
- dos funciones de LISP que seleccionan los elementos cabeza y cola
- (primero, segundo) de la celda. Si |x| es un |PTR TO LONG|, incluso se puede
- utilizar |x[0]| y |x[1]|.
- \espacio
- Tambi\'en se pueden escribir listas de celdas (atento a las comas):
- |<a,b,c>| \qquad como abreviatura de \qquad |<a|\|{}|<b|\|{}|<c|\|{}|NIL>>>|
- \espacio
- La unificaci\'on de E sirve de alternativa a la selecci\'on |Car()| y |Cdr()|:
- \ejemplos
- & |x <=> <a,b|\|{}|c>|\cr
- & |a+b+c|\cr
- en vez de:
- \ejemplos
- &|Car(x)+Car(Cdr(x))+Cdr(Cdr(x))|\cr
- \finsma
- La unificaci\'on de celdas-LISP se parece a la unificaci\'on con listas-E.
- Por ejemplo :
- \ejemplos
- &|x <=> <1,2|\|{}|a>|\cr
- equivale a:
- \ejemplos
- &|IF Car(x)=1|\cr
- &| IF Car(Cdr(x))=2|\cr
- &| a:=Cdr(Cdr(x))|\cr
- &| ...|\cr
- \finsma
- Tambi\'en existe el valor nil de LISP (|<>|), que equivale a |NIL| y |0|.
- \espacio
- Veamos algunas funciones disponibles (se\~nalar que |Cons()| {\bf solo} se
- puede usar por medio de |<...>|)
- \proto{h:=Car(c)}
- \pproto{t:=Cdr(c)}
- Fija el valor de la cabeza y la cola de la celda |c|.
- \proto{bool:=Cell(c)}
- Indica si |c| apunta a una celda, de forma que |Cell(<1>)=TRUE|,
- y |Cell(3.14)=FALSE|\null{}. No es una funci\'on r\'apida.
- \proto{n:=FreeCells()}
- Determina el n\'umero de celdas libres disponibles. Es muy lenta. No
- hay necesidad alguna de llamar a esta funci\'on, si no es por curiosidad.
- \proto{SetChunkSize(k)}
- Fija el tama\~no de los bloques reservados para celdas en |k|~kilobytes.
- Por omisi\'on es 128k. Esta funci\'on s\'olo se puede llamar una vez, y s\'olo
- antes de que tenga lugar la primera reserva constante (|<..>|). A partir de
- ese momento esta funci\'on no tiene ning\'un efecto.
- \espacio
- Resumiendo, hazte con un buen libro sobre LISP para entender bien la
- programaci\'on con celdas.
- \espacio
- Se pueden escribir funciones de LISP en E, con exactamente la misma
- funcionalidad:
- \ejemplos
- &|PROC append(x,y) IS IF x THEN <Car(x)||append(Cdr(x),y)> ELSE y|\cr
- &|PROC nrev(x) IS IF x THEN append(nrev(Cdr(x)),<Car(x)>) ELSE NIL|\cr
- &|PROC sum(x) IS IF x THEN Car(x)+sum(Cdr(x)) ELSE 0|\cr
- \finsma
- Tambi\'en se permite el uso de implementaci\'on destructiva para funciones
- como estas.
- \Espacio
- \subsec Notas t\'ecnicas.
- El recolector de residuos (RR) de E implementa un algoritmo de marca e
- intercambio conservativo que se ha comprobado que es entre~5 y~25 veces m\'as
- r\'apido que las distintas implementaciones l\'ogicas y funcionales del
- Amiga. Conservativo significa que en caso de duda, el~RR no libera la
- celda. Esto es necesario debido a que en un lenguaje sin tipos como el~E,
- el~RR podr\'{\i}a llegar facilmente a un valor que no es un puntero v\'alido,
- \noin El RR reserva bloques grandes (por omisi\'on 128k), en los cuales guarda
- las celdas. Si se acaban las celdas, recolectar\'a los residuos analizando
- la pila y los registros en busca de punteros al \'area de celdas, y los
- marcar\'a de forma recursiva. Tras eso, todas las celdas que no hayan sido
- marcadas se volver\'an a utilizar, y si la ganancia tras la recolecci\'on fue
- peque\~na, se reservar\'a un nuevo bloque (si eso falla se alcanzar\'a una
- excepci\'on |"NEW"|).
- \subsec Interacci\'on con otros valores de E.
- \item{$-$} No representa ning\'un problema almacenar otros valores en las celdas. Se pueden
- poner objetos, cadenas, reales, cualquier cosa en celdas sin confundir
- demasiado al~RR.
- \item{$-$} S\'{\i} es problem\'atico el almacenar celdas en otros valores, por ejemplo un
- puntero a una celda en un objeto din\'amico, ya que el~RR no ser\'a capaz
- de encontrarlo all\'{\i}. Sin embargo, pienso que ese caso aparecer\'a raras
- veces. Los punteros a celdas se pueden guardar de forma segura en
- variables globales o locales, incluso registros, y en cualquier
- estructura de datos de la pila. (!`y m\'as importante, en otras celdas!)
- \subsec Intr\'{\i}nsecos.
- \item{$-$} El RR no puede, de momento, recolectar celdas cuya lista-Car tenga una
- longitud |>1000| o similar, por ejemplo |<<<NIL:a>:b>:c>|, pero con 1000
- entradas en vez de~3. Esto es muy dif\'{\i}cil que ocurra ya que las listas
- de este tipo se suelen formar con \hbox{listas-Cdr}, que el~RR puede controlar
- hasta de tama\~no infinito. (alcanzar\'a una |"STCK"| si eso falla).
- \item{$-$} El c\'odigo ensamblador en l\'{\i}nea no debe poner cosas en la pila que no
- est\'en alineadas a 32~bits. Esto ya era necesario en v2.1b, pero ahora
- es m\'as imprescindible.
- \subsec Resumiendo.
- Hay una relaci\'on entre velocidad y espacio con respecto al tama\~no de
- los bloques. La reserva de bloques peque\~nos es, obviamente, interesante
- ya que no desperdicia memoria, sin embargo, al recolectar residuos, el
- trabajo de control de los punteros es proporcional al n\'umero de espacios.
- Por tanto:
- \item{$-$} Si es m\'as importante la velocidad, ajusta el tama\~no de los bloques de
- forma que s\'olo se necesite un bloque. Si el uso m\'aximo de memoria de
- celdas en cualquier momento es de~50k, un espacio de bloque de~100k~o
- 150k ofrecer\'a un rendimiento \'optimo.
- \item{$-$} Si lo m\'as importante es la memoria, en el ejemplo anterior un tama\~no de
- bloque de~20k~o 30k ser\'a bastante \'optimo en cuanto a uso de memoria.
- En resumen, temporiza el uso del algoritmo de celdas en situaciones
- complicadas para ver la relaci\'on velocidad\b/memoria m\'as apropiada.
- \endchapter\saltacap
- \beginchapter Cap\'{\i}tulo 10. Funciones\\de biblioteca\\y m\'odulos
- Como habr\'as notado en secciones anteriores el fragmento de c\'odigo enlazado
- de forma autom\'atica antes de tu c\'odigo, llamado {\sl c\'odigo de
- inicializaci\'on}, siempre abre las tres librer\'{\i}as\nota{N.T.: a lo que me refiero
- con librer\'{\i}a es en realidad una {\it biblioteca}, es decir, una biblioteca
- o colecci\'on de funciones. Lo que pasa es que debido a que en ingl\'es se les
- llaman libraries (como debe ser), parace ser que a uno se le pega m\'as r\'apido
- lo de librer\'{\i}a~\dots\enspace|:-(|} |intuition|, |dos| y |graphics|
- (y algunas veces |mathieeesigbas|), y debido a esto, el compilador tiene
- todas las llamadas a estas cuatro librer\'{\i}as (incluyendo |exec|) integradas
- en el compilador (hay unos cientos de ellas). Estas son hasta la versi\'on~3.00~(v39)
- de AmigaDos. Para llamar al |Open()| de `dos' s\'olo tienes que escribir:
- \ejemplos
- &|handle:=Open('mifichero',OLDFILE)|\cr
- o para |AddDisplayInfo()| de la librer\'{\i}a |graphics|:
- \ejemplos
- &|AddDisplayInfo(midispinfo)|\cr
- \finsma
- Es tan sencillo como eso.
- \seccion Interface con el sistema Amiga con los m\'odulos de v39.
- Para usar cualquier otra librer\'{\i}a, a parte de las cinco de la secci\'on
- anterior, debes recurrir a los m\'odulos. Igualmente si deseas utilizar
- alg\'una definici\'on de |OBJECT|o o |CONST| de los includes del Amiga, como es
- normal en~C o ensamblador, tambi\'en necesitar\'as los m\'odulos. Los m\'odulos
- son ficheros binarios que pueden incluir definiciones de constantes,
- objetos librer\'{\i}as y funciones (c\'odigo). El hecho de que sean binarios
- tiene la ventaja sobre el \ASCII/ (como en~C y en ensamblador), que no es
- necesario compilarlos una y otra vez, cada vez que se compila un
- programa. La desventaja es que no se puede leer con tanta facilidad, se
- necesita una utilidad como |ShowModule| para ver su contenido. Los m\'odulos
- que contienen las definiciones de librer\'{\i}as se encuentran en el directorio
- raiz de |EMODULES:| (el directorio |modules/| en la distribuci\'on), las
- definiciones de constantes\b/objetos est\'an en los subdirectorios,
- estructurados de la misma forma que los originales de Commodore.
- \Espacio
- \ejemplos
- \qquad Sintaxis:&|MODULE |\<nombrem\'odulo>|, ...|\cr
- \finsma
- Lee un m\'odulo. Un m\'odulo es un fichero binario con informaci\'on sobre
- librer\'{\i}as, constantes, y a veces, funciones. El uso de m\'odulos permite
- usar librer\'{\i}as y funciones que eran desconocidas por el compilador.
- \espacio
- Veamos un ejemplo, una versi\'on reducida del ejemplo
- |source|\b/|Examples|\b/|asldemo.e|, que usa m\'odulos para obtener un requester de
- ficheros de la |Asl.library|~2.0.
- \begintt
- MODULE 'Asl', 'libraries/Asl'
- PROC main()
- DEF req:PTR TO filerequester
- IF aslbase:=OpenLibrary('asl.library',37)
- IF req:=AllocFileRequest()
- IF RequestFile(req)
- WriteF('Fichero: "\s" in "\s"\n',req.file,req.drawer)
- ENDIF
- FreeFileRequest(req)
- ENDIF
- CloseLibrary(aslbase)
- ENDIF
- ENDPROC
- \endtt
- el compilador obtiene del m\'odulo |'asl'| las definiciones de funciones
- de |asl| como |RequestFile()|, y la variable global |aslbase|, que s\'olo
- necesita que el programador la inicialize. De |'libraries/Asl'| obtiene la
- definici\'on del objeto |'filerequester'|, el cual se usa para leer el
- fichero que seleccion\'o el ususario.
- \espacio
- Bueno, ?`Pensabas que era m\'as dif\'{\i}cil tener un requester de ficheros en~E?
- \seccion Compilando m\'odulos propios.
- A partir de la versi\'on v3 puedes agrupar en un solo fuente todos los |PROC|s, |CONST|s,
- |OBJECT|os y, hasta cierto punto tambi\'en las variables globales, que te
- parezca esten relacionados entre s\'{\i} de alguna forma. Utiliza |OPT MODULE| para
- indicar al compilador~EC que ese fichero se
- supone que es un m\'odulo, y luego comp\'{\i}lalo a un fichero |.m| que se podr\'a usar en
- el programa principal, igual que con los dem\'as m\'odulos.
- \espacio
- Por omisi\'on todos los elementos de un m\'odulo son |PRIVATE|, es decir, no
- son accesibles al c\'odigo que importa el fichero |.m|. Para hacer visibles
- los elementos que quieras, simplemente escribe |EXPORT| antes de ellos:
- \begintt
- EXPORT ENUM TESTING,ONE,TWO,THREE,FOUR
- EXPORT DEF var_global_importante, bla:PTR TO x
- EXPORT OBJECT x
- sig, indice, termino
- ENDOBJECT
- EXPORT PROC burp()
- /* lo que sea */
- ENDPROC
- \endtt
- |EXPORT| es \'util para hacer la distinci\'on entre privado y p\'ublico,
- especialmente, cuando se puede acceder a todas las funciones de un objeto
- mediante |PROC|s, puedes desear mantener un |OBJECT|o privado como una forma
- efectiva de {\sl ocultamiento de datos}. |EXPORT| puede aparecer en cualquier
- l\'{\i}nea, en cuyo caso no afectar\'a a nada.
- \noin Si es necesario exportar {\sl todos} los elementos de un m\'odulo (por
- ejemplo, uno que s\'olo tenga constantes), con |OPT EXPORT| se exportr\'a
- todo, sin que haga falta utilizar |EXPORT|s individuales.
- \noin Las variables globales necesitan una atenci\'on especial:
- \item{$-$} Intenta eludir muchas variables globales. El tener muchas variables
- globales en los m\'odulos hace los proyectos propensos a errores.
- \item{$-$} Las variables globales de un m\'odulo no pueden tener inicializaciones
- directas en la sentencia |DEF| (la raz\'on de esto se aclar\'a m\'as tarde). Por ejemplo:
- \itemitem{} |DEF a |\qquad y no\qquad |DEF a=1|
- \itemitem{} |DEF a:PTR TO x|\qquad y no\qquad |DEF a[10]:ARRAY OF x|
- \item{$-$} Las variable globales de un m\'odulo que no se exportan operan como
- locales al m\'odulo, es decir, nunca chocar\'an con globales de otros
- m\'odulos. Aquellas exportadas, se combinan con las dem\'as, es decir, si
- se usa una variable con el mismo nombre, tanto en el programa principal
- como en m\'odulos, \'esta ser\'a una s\'ola y la misma para los dos. Este es
- el motivo de que se pueda escribir |DEF a[10]:ARRAY OF x| en el programa
- principal, y |EXPORT DEF a:PTR TO x| en el m\'odulo, para compartir el
- arreglo. Adem\'as, si ambos usan, por ejemplo, |gadtools.m|, s\'olo uno de
- los dos tiene que inicializar |gadtoolsbase| para que ambos puedan
- hacer llamadas a la librer\'{\i}a. Si no quieres compartir las bases de las
- librer\'{\i}as (es decir, quieres tener una base de librer\'{\i}a local,privada),
- simplemente redecl\'arala en un |DEF| de un m\'odulo que no la |EXPORT|e. Si
- exportas una variable en un m\'odulo de proprosito general, aseg\'urate de
- que tenga un nombre \'unico.
- \item{$-$} El uso de variables en m\'odulos que proporcionan tipos de datos de
- prop\'osito general necesita de una atenci\'on especial, ya que el m\'odulo
- puede ser usado desde m\'as de un m\'odulo, en cuyo caso no est\'a claro
- quien es el responsable de los recursos. Ten esto bien en cuenta.
- \Espacio
- \subsec Uso de m\'odulos dentro de m\'odulos.
- Esto requiere una atenci\'on extra. Si el m\'odulo (B) que incluyes en tu
- propio m\'odulo (A) es uno que s\'olo declara |CONST|s, |LIBRARY|s y |OBJECT|os
- (sin c\'odigo) no sucede nada especial, sin embargo, si B incluye |PROC|s,
- entonces es obvio que ese c\'odigo necesita ser enlazado m\'as tarde con el
- programa principal cuando se enlace A\null{}. Por ello, si un programa principal
- usa A, B debe estar presente en la compilaci\'on. El hecho de que A necesite
- a B se guarda en A, y se puede ver con |ShowModule|. Esta cadena de
- usos puede crecer creando un \'arbol de dependencias, que tiene como
- resultado que aunque s\'olo utilices un m\'odulo en tu programa, se enlazar\'an
- a \'el de forma autom\'atica unos cuantos m\'as. Por ello, el sistema de
- m\'odulos de~E mantiene de forma autom\'atica las dependencias para las que
- otros lenguajes necesitan makefiles. |EC|~tambi\'en permite dependencias
- circulares, y lee/enlaza un m\'odulo a lo sumo una vez (es decir, no enlaza
- m\'odulos que no se usaron). Una cosa que el sistema de m\'odulos de E no
- realiza de forma autom\'atica es recompilar m\'odulos dependientes. Si
- cambias B, a menudo ser\'a necesario recompilar A tambi\'en, ya que puede
- hacer referencia de offsets, etc, de la versi\'on antigua de B, lo cual
- puede provocar que el c\'odigo rompa. Si esto se empieza a complicar en tu
- proyecto, puedes usar una utilidad como |E-Build|.
- \noin Prueba el nuevo |ShowModule| para ver lo que pone |EC| en los m\'odulos.
- \Espacio
- \subsec Inclusi\'on de m\'odulos de otros directorios.
- Por omisi\'on, al nombre del m\'odulo se le pone como prefijo |EMODULES:|
- para obtener el fichero en concreto. Ahora puedes anteponer un |*| al
- m\'odulo para indicar el directorio en el que encuentra el c\'odigo fuente, de
- forma que si en el fuente |WORK:E/burp.e| apareciese:
- \ejemplos
- &|MODULE 'bla', '*bla'|\cr
- el compilador buscar\'{\i}a los m\'odulos |EModules:bla.m| y |WORK:E/bla.m|.
- \espacio
- Esta es, naturalmente, la forma de incluir componentes de tu
- aplicaci\'on en otras partes. Si escribes m\'odulos que usas en muchos de
- tus programas, ser\'{\i}a bastante conveniente guardarlos dentro de la
- jerarqu\'{\i}a de |EModules:|, y el lugar adecuado para esto es el directorio
- |EModules:other/|.
- \seccion El cach\'e de m\'odulos.
- {\it (Se trata en detalle en la seccion sobre |ShowCache/FlushCache|).}
- \endchapter\saltacap
- \beginchapter Cap\'{\i}tulo 11. Expresiones\\entrecomilladas
- Las expresiones entrecomilladas empiezan con una comilla inversa ``|`|''.
- Su valor {\bf no} es el resultado de la computaci\'on de la expresi\'on, sino la
- direcci\'on del c\'odigo que la computa. Este resultado se puede utilizar
- como una variable, o como argumento de ciertas funciones. Por ejemplo,
- \ejemplos
- &|mifunc:=`x*x*x|\cr
- hace que ahora |mifunc| sea un puntero a una {\it funci\'on} que computa |x^3| cuando se
- eval\'ua. Estos punteros a funciones son bastante diferentes de los |PROC|s
- normales, y nunca se deben mezclar o confundir. La principal diferencia
- de las expresiones entrecomilladas es que s\'olo son expresiones simples, y
- por tanto no pueden tener sus propias variables locales. En nuestro
- ejemplo, |x| es o una variable global o una variable local. Ah\'{\i} es donde
- debemos tener precauci\'on: si evaluamos |mifunc| en alg\'un otro lugar del
- mismo |PROC|, |x| puede ser local, pero si |mifunc| se pasa como par\'ametro a
- otro |PROC|, y luego se eval\'ua, entonces |x| debe ser global. El compilador
- no realiza esta comprobaci\'on por t\'{\i}.
- \proto{Eval(func)}
- Simplemente eval\'ua la expresi\'on entrecomillada (|exp = Eval(`exp)|).
- Debido a que E es, de alguna forma, un lenguaje sin tipos, el
- escribir |Eval(x*x)| de forma accidental en lugar de |Eval(`x*x)| pasar\'a
- desapercibido al compilador, y propiciar\'a muchos problemas en tiempo de
- ejecuci\'on: el valor del |x*x| se usar\'a como un puntero a c\'odigo.
- \espacio
- Para entender el motivo por el que las expresiones entrecomilladas
- representan una caracter\'{\i}stica importante piensa en los siguientes casos:
- si quisieras realizar una serie de acciones en un grupo de variables
- diferentes, normalmente escribir\'{\i}as una funci\'on y la llamar\'{\i}as con
- diferentes argumentos. Pero, ?`qu\'e ocurre cuando el elemento que quieres
- dar como argumento es un fragmento de c\'odigo? En lenguajes tradicionales
- esto no ser\'{\i}a posible, por lo que necesitar\'{\i}as 'copiar' los bloques de
- c\'odigo que representan la funci\'on, y poner la expresi\'on en ellos. En~E
- no. Digamos que quieres escribir un programa que mida el tiempo de
- ejecuci\'on de diferentes expresiones. En~E simplemente escribir\'{\i}as:
- \begintt
- PROC mide(func,titulo)
- -> realizar todo tipo de inicializaciones del tiempo
- Eval(func)
- -> y el resto
- WriteF('\s tardo \d en ejecutarse\n',titulo,t)
- ENDPROC
- \endtt
- y luego lo llamas con:
- \ejemplos
- &|mide(`x*x*x,'multiplicacion')|\cr
- &|mide(`calcenorme(),'calculo grande')|\cr
- \finsma
- En cualquier otro lenguaje imperativo, necesitar\'{\i}as escribir copias de
- |mide()| para cada llamada, o poner cada expresi\'on en una funci\'on
- diferente. Este es un ejemplo sencillo, piensa en lo que podr\'{\i}as hacer
- con estructuras de datos (|LIST|as) y c\'odigo sin evaluar:
- \ejemplos
- &|funcsdibu:=[`Plot(x,y,c),`Line(x,y,x+10,y+10,c),`Box(x,y,x+20,y+20,c)]|\cr
- \finsma
- La idea de usar funciones como variables normales\b/valores no
- es nuevo de~E, las expresiones entrecomilladas vienen del
- LISP, que adem\'as tambi\'en tiene las llamadas funciones {\sl Lambda}, de alguna
- forma m\'as potentes, y que tambi\'en se pueden dar como argumentos a
- funciones. Las expresiones entrecomilladas de~E se pueden ver como
- {\sl lambdas} sin par\'ametros (o s\'olo de par\'ametro global).
- \seccion Funciones predefinidas.
- \proto{MapList(dirvar,lista,listavar,func)}
- Aplica una funci\'on a todos los elementos de la lista y retorna los
- resultados en |listavar|. |func| debe ser una expresi\'on entrecomillada,
- y |var| (que tomar\'a todos los valores de la lista) se dar\'a por referencia.
- Retorna |listavar|.
- \Ejemplos
- Ejemplo:& |MapList({x},[1,2,3,4,5],r,`x*x) resulta con r: [1,4,9,16,25]|\cr
- \proto{ForAll(dirvar,lista,func)}
- Retorna |TRUE| si la funci\'on (expresi\'on entrecomillada) se eval\'ua a |TRUE|
- para todos los elementos de la lista, y |FALSE| en otro caso. Tambi\'en se
- usa para aplicar una cierta funci\'on a todos los elementos de la lista:
- \ejemplos
- |ForAll({x},['uno','dos','tres'],`WriteF('ejemplo: \s\n',x))|\cr
- \proto{Exists(dirvar,lista,func)}
- Como |ForAll()|, s\'olo que \'esta retorna |TRUE| si para alg\'un elemento la
- funci\'on se eval\'ua a |TRUE| (|<>0|). |ForAll()| siempre eval\'ua todos los
- elementos, pero |Exists()| probablemente no.
- \proto{SelectList(v,lista,listavar,exprentrecom)}
- Muy parecida a |MapList()|, s\'olo que ahora no guarda el resultado de
- |exprentrecom|, lo usa como valor booleano, y s\'olo los valores para los
- cuales es cierta se guardan en |listavar| ---que debe poder guardar el
- mismo n\'umero de elementos que |lista|. Retorna la longitud de |listavar|.
- \Ejemplos
- Ejemplo:&|SelectList({x},[1,2,0,3,NIl],r,`x<>0) resulta con r=[1,2,3]|\cr
- \finsma
- Ejemplo pr\'actico de utilizaci\'on:
- \noin Reservamos diferentes tama\~nos de memoria en una sentencia, los comprobamos
- a la vez, y los liberamos todos de una vez, pero s\'olo los que se
- pudieron reservar. (Este ejemplo necesita v37+)
- \begintt
- PROC main()
- DEF mem[4]:LIST,x
- MapList({x},[200,80,10,2500],mem,`AllocVec(x,0)) -> reservamos
- WriteF(IF ForAll({x},mem,`x) THEN '!`Si!\n' ELSE '!`No!\n') -> ?`exito?
- ForAll({x},mem,`IF x THEN FreeVec(x) ELSE NIL) -> solo libera <>NIL
- ENDPROC
- \endtt
- F\'{\i}jate en la ausencia de iteraci\'on en este c\'odigo. Intenta escribir
- este ejemplo en cualquier otro lenguaje para ver porqu\'e es especial.
- \endchapter\saltacap
- \beginchapter Cap\'{\i}tulo 12. Los n\'umeros\\Reales
- Los n\'umeros reales en E (o FLOATs, como quieras) son bastante diferentes de
- los de otros lenguajes. Esto es debido, sobre todo, al hecho de que~E realmente no
- discrimina entre tipos de valores. Te aviso que debes
- entender {\bf bien} esta secci\'on antes de intentar usar reales.
- \Espacio
- En E un real no es m\'as que otro valor de 32 bits. El compilador de~E
- los trata como si fueran enteros o punteros, con la diferencia de que su
- representaci\'on interna significa algo totalmente diferente. El formato
- de los reales en~E es el estandard |IEEEsingle|.
- \noin Un valor real es similar a un entero, con la salvedad de que tiene un
- punto en alg\'un lugar. Por ejemplo, los siguientes son reales v\'alidos:
- \ejemplos
- &$3.14159\qquad .1\qquad 1.\qquad -12345.6$\cr
- y estos no lo son:
- \ejemplos
- &$.\qquad 1234$\cr
- (es decir, debe tener al menos un |.| y un caracter |0-9|).
- \espacio
- Puedes usar estos valores en pr\'acticamente todos lo lugares en los que
- es legal un valor |LONG|, es decir, si tienes una funci\'on o estructura de
- datos que utiliza valores |LONG| cualesquiera, tambi\'en utilizar\'a reales.
- \begintt
- DEF f=3.14
- myobj.x:=.1
- fun(f,2.73)
- \endtt
- \seccion Computaci\'on con reales.
- Debido a que los reales son como |LONG|s para E, \'este utilizar\'a con toda
- seguridad la aritm\'etica de enteros con ellos cuando se usan en una
- expresi\'on, lo cual seguramente no es lo que quieres. Adem\'as, tambi\'en
- ser\'{\i}a interesante poder convertir de enteros a reales y viceversa. Con
- el operador ``|!|'' se puede hacer todo esto.
- \espacio
- Supongamos que en los siguientes ejemplos |a|,|b|,|c| contienen valores
- enteros, y que |x|,|y|,|z| contienen valores reales.
- \espacio
- Por omisi\'on, una expresi\'on en E se considera una expresi\'on entera. Lo
- que hace |!| cuando apararece en una expresi\'on es:
- \item{$-$} Cambia la expresi\'on de entero a real. Cualquier operador que le siga
- (|+ * - / = <> > < >= <=|) realizar\'a operaciones con reales. |!| puede
- aparecer tantas veces como quieras.
- \item{$-$} La expresi\'on que aparece antes de |!|, si hubo alguna, se convierte al
- tipo apropiado.
- \espacio
- Ejemplos:
- \begintt
- x:=a! -> convierte "a" en real, y pone el resultado en x. "a" es
- -> una expresion entera, que se cambia por real, lo cual
- -> implica una conversion.
- a:=!x! -> convierte "x" a entero y guarda el resultado en "a".
- x:=y -> aqui no se necesita "!" ya que no es necesario ningun
- x:=Ftan(y) -> operador matematico ni conversion.
- x:=!y*z -> "*" actua sobre 'y' y 'z' como reales porque "!" denota
- -> el todo como expresion real. El resultado real va a x.
- a:=b!*x+y! -> un ejemplo mas complejo: el entero 'b' se convierte en
- -> real, luego se multiplica por 'x' (como reales) y se le
- -> suma 'y' (como reales). El resultado se convierte en
- -> entero y se pone en el entero 'a'".
- \endtt
- \begintt
- x:=!y*z-z*y+(a!)+z/z -> los operadores (+*-/) se computan como reales,
- z:=!x*Fsin(!x*y) -> y el entero 'a' se convierte a real en algun
- -> lugar de la expresion. Como ( y ) denotan una
- -> nueva expresion, tiene su propio estado de !.
- -> La misma idea para la segunda funcion.
- IF !x<0.1 THEN WriteF('!`Valor real demasiado bajo!\n')
- -> Como ves "!" tambien sirve para los seis operadores de comparacion.
- \endtt
- \seccion Funciones de reales predefinidas.
- Se incluyen algunas funciones matem\'aticas de transformaci\'on, es
- probable que se incluyan m\'as en el futuro.
- \proto{Fsin(y)}
- \pproto{Fcos(y)}
- \pproto{Ftan(y)}
- Las funciones |sin()|,~\dots\enspace de siempre. Funcionan con radianes.
- \proto{Fabs(y)}
- Computa el valor absoluto de |y| ($\vert y\vert$).
- \proto{Ffloor(y)}
- \pproto{Fceil(y)}
- Computa el entero m\'as pr\'oximo a |y| (menor y mayor respectivamente).
- \proto{Fexp(y)}
- \pproto{Flog(y)}
- \pproto{Flog10(y)}
- \pproto{Fpow(y,z)}
- \pproto{Fsqrt(y)}
- Computa $e^y$, $\ln y$, $\log_{10} y$, $z^y$ y $\sqrt{y}$.
- \proto{x,n:=RealVal(s)}
- Analiza la cadena |s| para producir el valor real |x|. No tiene en
- cuenta los espacios o tabuladores que lleve delante. |n| es el n\'umero de
- caracteres analizados desde el comienzo de la cadena, o |0| si la cadena no
- representa a un valor real. |x| valdr\'a en ese caso $0.0$. Acepta valores
- negativos (e incluso n\'umeros sin |.|).
- \Ejemplos
- Ejemplos:&|RealVal(' 3.14 ')|\qquad resulta $3.14$, $5$\cr
- &|RealVal('blabla')|\qquad resulta $0.0$, $0$\cr
- \proto{s:=RealF(s,x,n)}
- Retorna en |s| el valor real |x| como cadenaE, con |n| decimales. El
- m\'aximo de |n| es |8|, incluso menos si la parte entera del n\'umero es grande.
- Un valor de |n| igual a |0| indicar\'a que no se quiere fracci\'on. La
- cadena se retorna como resultado, para poder utilizarla en un |WriteF()|.
- \Ejemplos
- Ejemplo:&|WriteF('real=\s\n',RealF(s,3.14159),4)|\qquad resulta |real=3.1416|\cr
- \finsma
- |RealF()| se afana en realizar redondeos razonables para un cierto |n|,
- como muestra el ejemplo. Los n\'umeros negativos tambi\'en son tratados de
- forma correcta.
- \ejemplos
- &|RealF(s,-3.14159,0)|\qquad resulta $-3$\cr
- \seccion Notas sobre la implementaci\'on de los reales.
- Como se dijo antes, el formato de reales de~ E es el {\sc IEEE} (simple),
- esto significa que el c\'odigo con reales anterior, que usaba el formato
- {\sc FFP} con las funciones |SpXxx| se debe reescribir (como se indicaba en la
- documentaci\'on de la v2.1b del compilador). |EC|~v3.0 ya no apoya directamente
- la librer\'{\i}a |mathffp|, y tendr\'as que abrir esta librer\'{\i}a
- directamente si quieres usarla.
- \espacio
- Se eligi\'o {\sc IEEE} simple porque:
- \item{$-$} Los {\sc IEEE} dobles no entran en un |LONG|.
- \item{$-$} Las rutinas del formato {\sc FFP} no utilizan el |68881| si est\'a presente, las
- de {\sc IEEE} s\'{\i} lo hacen. Adem\'as, el formato {\sc IEEE} es compatible con el
- |68881|, que tambi\'en utiliza el formato {\sc IEEE}.
- \item{$-$} {\sc IEEE} es el formato estandard para reales, reconocido en todos los
- lugares, lo cual permite compatibildad de ficheros de datos entre
- software/plataformas.
- \espacio
- Las rutinas de reales en E usan la mathieeesingbas.library y la
- mathieeesingtrans.library, las cuales no se ofrec\'{\i}an con la antigua
- versi\'on~1.3 del sistema operativo.\nota{se sabe que la v3.1 (v40) del
- sistema operativo del Amiga contiene un error en el c\'odigo de {\sc IEEE}.
- Usa un |SetPatch| que lo corrija.} Esto quiere decir que si quieres
- escribir bajo\b/apoyar la~v1.3 del sitema operativo, y quieres usar los
- reales {\it internos}, debes asegurarte de que esas librer\'{\i}as est\'an presentes
- (paracen estar disponibles, ?`quizas por medio de Commodore?).
- \noin Tanto |EC| como los programas que genera no abren esas librer\'{\i}as
- mientras no se usen reales.
- \espacio
- Si falla todo lo dem\'as, siempre puedes usar otras librer\'{\i}as de reales
- para usar reales bajo~1.3. Yo recomendar\'{\i}a el m\'odulo |tools/longreal.m|,
- el cual usa dobles.
- \espacio
- En un futuro, es probable que |EC| permita que las llamadas de la
- librer\'{\i}a |mathieee| se substituyan por c\'odigo de |68881| en l\'{\i}nea de forma
- transparente.
- \endchapter\saltacap
- \beginchapter Cap\'{\i}tulo 13. Manejo\\de Excepciones
- El mecanismo de excepciones\nota{en E el t\'ermino {\sl excepci\'on} tiene poco que
- ver con las excepciones o interrupciones causadas directamente por los
- procesadores |680x0|.} de E es b\'asicamente igual al del lenguaje
- ADA; proporciona una reacci\'on a los errores en tu programa, y un manejo
- complejo de recursos.
- \espacio
- Un manejador de excepciones es un fragmento de c\'odigo que se invoca
- cuando sucede un error en tiempo de ejecuci\'on. El sistema en tiempo de
- ejecuci\'on, o t\'u mismo, puedes {\sl se\~nalar} que algo ha ido mal (esto es lo
- que se llama {\sl lanzar una excepci\'on}), y luego el sistema en tiempo de
- ejecuci\'on probar\'a y buscar\'a el manejador de excepciones apropiado. Digo
- {\it apropiado} porque un programa puede tener m\'as de un manejador de
- excepciones, en todos los niveles del programa. La siguiente puede ser
- la definici\'on de una funci\'on normal (como ya sabemos):
- \ejemplos
- &|PROC bla()|\cr
- &| /* ... */|\cr
- &|ENDPROC|\cr
- mientras que una funci\'on con un manejador de excepciones puede ser:
- \ejemplos
- &|PROC bla() HANDLE|\cr
- &| /* ... */|\cr
- &|EXCEPT|\cr
- &| /* ... */|\cr
- &|ENDPROC|\cr
- donde el bloque entre |PROC| y |EXCEPT| se ejecuta como siempre, y si no hay
- ninguna excepci\'on se salta el bloque entre |EXCEPT| y |ENDPROC|, abandonando
- el procedimiento en |ENDPROC|\null{}. Si se alcanza alguna excepci\'on, ya sea
- dentro del procecimiento, o en cualquier funci\'on llamada desde ese
- bloque, se invocar\'a un manejador de excepciones.
- \seccion Uso de la funci\'on |Raise()|.
- Hay muchas formas de {\sl lanzar} una excepci\'on, la m\'as sencilla es por
- medio de la funci\'on |Raise()|:
- \proto{|Raise(IDexcepcion=0)|}
- donde \enspace|IDexcepcion|\enspace es simplemente una constante que define el tipo de
- excepci\'on, y lo usan los controladores para determinar lo que fue m\'al.
- \begintt
- ENUM NOMEM,NOFILE /* y otros */
- PROC bla() HANDLE
- DEF mem
- IF (mem:=New(10))=NIL THEN Raise(NOMEM)
- mifunc()
- EXCEPT
- SELECT exception
- CASE NOMEM
- WriteF('!`Sin memoria!\n')
- /* ... y otras */
- ENDSELECT
- ENDPROC
- PROC mifunc()
- DEF mem
- IF (mem:=New(10))=NIL THEN Raise(NOMEM)
- ENDPROC
- \endtt
- \Espacio
- La variable |exception| del manejador siempre contiene el valor del
- argumento de la llamada al |Raise()| que lo invoc\'o.
- \noin La funci\'on |Raise()| invoca al manejador de la funci\'on |bla()| en ambos
- |New()|, y retorna correctamente al que hab\'{\i}a llamado a |bla()|. La llamada
- |New()| de |mifunc()| habr\'{\i}a llamado a su manejador de excepciones si \'esta
- tuviera alguno. El alcance de un manejador va desde el comienzo del |PROC|
- en que se define hasta la palabra clave |EXCEPT|, incluyendo todas las
- llamadas que se hagan desde el procedimiento.
- \espacio
- Esto tiene tres consecuencias:
- \item{$A.$} Los manejadores se organizan de forma recursiva, y el manejador que se
- invoca se selecciona dependiendo de las llamadas de las funciones en
- tiempo de ejecuci\'on.
- \item{$B.$} Si se lanza una excepci\'on dentro de un manejador, se invoca el
- manejador de nivel justamente anterior. Esta caracter\'{\i}stica de los
- manejadores se puede usar para implementar esquemas complejos de
- reserva recursiva de recursos con gran facilidad, (como se ver\'a).
- \item{$C.$} Si se lanza una excepci\'on en un nivel en el que no existe un manejador
- de menor nivel (o en programas que no tienen ning\'un tipo de
- manejadores), se finaliza el programa. (es decir, |Raise(x)| tiene el
- mismo efecto que |CleanUp(0)|)
- \espacio
- Veamos otras funciones de manejadores:
- \proto{Throw(IDexcepcion,valor)}
- Como |Raise()|, s\'olo que ahora lleva un valor arbitrario con ellas. Y
- luego se puede escrutar ese valor en el manejador con la variable
- |exceptioninfo|.
- \proto{ReThrow()}
- No tiene argumentos. Simplemente hace un |Throw()| con el valor de
- excepci\'on actual. S\'{\i} y solo s\'{\i} es |<>0|
- \seccion Definici\'on de excepciones para funciones predefinidas (|RAISE/IF|).
- Con lo que vimos hasta ahora de las excepciones ya tenemos grandes
- ventajas sobre la forma de definir la funci\'on |error()| de siempre,
- aunque hay que escribir demasiado para comprobrar la igualdad a |NIL| de
- cada llamada a |New()|.
- \noin El sistema de manejo de excepciones de E permite la definici\'on de
- excepciones para todas las funciones de~E (como |New()|, |OpenW()|, etc.), y
- para todas las funciones de Librer\'{\i}a (|OpenLibrary()|, |AllocMem()|, etc.),
- incluso para aquellas que se incluyen como m\'odulos.
- \Espacio
- \ejemplos
- \qquad Sintaxis:&|RAISE |\<IDexception>| IF |\<func> \<comp> \<valor>|, ...|\cr
- la parte que sigue a |RAISE| se puede repetir con una |,|.
- \Ejemplos
- Ejemplo:&|RAISE NOMEM IF New()=NIL,|\cr
- &| NOLIBRARY IF OpenLibrary()=NIL|\cr
- la primera l\'{\i}nea quiere decir algo como: {\sl siempre que una llamada a |New()|\/
- resulte en |NIL|, lanza autom\'aticamente la excepci\'on |NOMEM|}. \<comp> puede
- ser cualquiera entre |= <> > < >= <=|. Tras esta definici\'on, a lo largo
- de nuestros programas podemos escribir:\quad|mem:=New(size)|\quad sin tener que
- escribir\quad|IF mem=NIL THEN Raise(NOMEM)|.
- \noin F\'{\i}jate que la \'unica diferencia es que |mem| nunca recibe un valor si
- el sistema invoca al manejador: para cada llamada a |New()| se genera
- c\'odigo que comprueba su resultado y llama a |Raise()| si es necesario.
- \espacio
- Vamos a implementar un peque\~no ejemplo que ser\'{\i}a complejo de resolver
- sin manejo de excepciones: llamamos a una funci\'on recursivamente, y
- reservamos un recurso en cada llamada (en este caso se reserva memoria
- antes de la llamada recursiva, y se libera despu\'es). ?`Qu\'e ocurre si en
- alg\'un momento en la recursi\'on ocurre un fallo severo, y tenemos que dar
- el programa por terminado? Cierto, al dejar el programa no podr\'{\i}amos (en
- un lenguaje convencional) liberar todos los recursos reservados en
- niveles de recursi\'on inferiores, debido a que todos los punteros a tales
- \'areas de memoria se encuentran en variables locales inalcanzables. En E,
- simplemente lanzamos una excepci\'on, y lanzamos otra al final del manejador,
- llamando de esta forma recursivamente a los manejadores, y liberando
- todos los recursos. Ejemplo:
- \begintt
- CONST SIZE=100000
- ENUM NOMEM /*, ... */
- RAISE NOMEM IF AllocMem()=NIL
- PROC main()
- reserva()
- ENDPROC
- PROC reserva() HANDLE
- DEF mem -> veamos cuantos bloques de
- mem:=AllocMem(SIZE,0) -> memoria se pueden obtener.
- reserva() -> realiza la recursion.
- EXCEPT DO
- IF mem THEN FreeMem(mem,SIZE)
- ReThrow() -> llama recursivamente a los manejadores.
- ENDPROC
- \endtt
- \espacio
- Por supuesto, esto es una simulaci\'on de un problema de programaci\'on
- natural, que normalmente es bastante m\'as complejo, y que por ello hace
- m\'as evidente la necesidad del manejo de excepciones. Hecha un vistazo al
- c\'odigo fuente de la utilidad \enspace|D.e|\enspace para ver un programa real de ejemplo,
- en el que el manejo de errores se complicar\'{\i}a sin manejo de excepciones.
- \espacio
- El |DO| que va despu\'es de |EXCEPT| indica que en lugar de saltar a
- |ENDPROC|, el c\'odigo principal simplemente contin\'ua la ejecuci\'on en el
- manejador cuando llega a ese punto. Tambi\'en fija la excepci\'on a~0.
- Puede ser \'util si en el manejador liberas recursos locales al |PROC|.
- \seccion Uso de |ID| de excepciones.
- En realidad un |ID | de excepci\'on es un valor de 32-bits normal (por
- supuesto), y puedes pasar lo que quieras al manejador de excepciones:
- por ej., algunos los usan para pasar cadenas de descripci\'on de errores:
- \ejemplos
- &|Raise('!`No pude abrir la "gadtools.library"!')|\cr
- \finsma
- Sin embargo, si quieres usar las excepciones de una forma expandible y
- deseas poder usar m\'odulos futuros que lanzen excepciones sin definir en
- tu programa, sigue las siguientes normas:
- \item{$-$} Usa y define el |ID| 0 como {\sl no error} (finalizaci\'on normal).
- \item{$-$} Usa los IDs 1-10000 para excepciones espec\'{\i}ficas de tu programa.
- Def\'{\i}nelos como siempre con |ENUM|:
- \itemitem{} |ENUM OK,NOMEM,NOFILE, ...|
- \itemitem{} (|OK| ser\'a 0, y los dem\'as 1+)
- \item{$-$} Los |ID|'s |12336| a |2054847098| (todos formados por letras may\'usculas
- o min\'usculas y d\'{\i}gitos entre comillas, y tienen longitud 2, 3 o 4)
- est\'an reservados para excepciones comunes. Una excepci\'on com\'un es una
- excepci\'on que no es necesario definir en tu programa, y que puede ser
- usada por los implementadores de m\'odulos (con funciones) para lanzar
- excepciones: por ejemplo, si dise\~nas un conjunto de procedimientos que
- realizan cierta tarea, puede ser que desees lanzar excepciones. Dado
- que podr\'{\i}as querer usar esas funciones en varios programas, no ser\'{\i}a
- pr\'actico tener que coordinar los |ID|s con el programa principal, es m\'as,
- si usas m\'as de un conjunto de funciones (en un m\'odulo, en el futuro) y
- cada m\'odulo tuviera un identificador diferente para {\sl sin memoria}, las
- cosas se har\'{\i}an impracticables. Ah\'{\i} es donde entran las excepciones
- comunes: el |ID | com\'un para sin-memoria es |"MEM"| (incluyendo las
- comillas): cada implementador deber\'{\i}a escribir simplemente
- \itemitem{} |Raise("MEM")|
- \item{} desde cualquier procediemiento, y el programador que use el m\'odulo s\'olo
- necesita proporcionar un manejador de exepciones que entienda |"MEM"|.
- \espacio
- \item{} Futuros m\'odulos que contengan conjuntos de funciones especificar\'an las
- excepciones que pueden alcanzar cada uno de esos procedimientos, y si
- \'estas coinciden con los |ID|s de otros procedimientos, la tarea del
- programador que tiene que tratar con excepciones se ver\'a simplificada
- significativamente.
- \Ejemplos
- Ejemplos:\cr
- (sistema)\cr
- \esptab
- |"MEM"|&sin memoria\cr
- |"FLOW"|&pila (pr\'acticamente) llena\cr
- |"STCK"|&recolector de residuos con problemas de pila\cr
- |"^C"|&Ruptura por Control-C\cr
- |"ARGS"|&args err\'oneos\cr
- \esptab
- (exec/librerias)\cr
- \esptab
- |"SIG"|&no se pudo reservar se\~nal\cr
- |"PORT"|&no se pudo crear puerto de mensajes\cr
- |"LIB"|&library no disponible\cr
- |"ASL"|&no asl.library\cr
- |"UTIL"|&no utility.library\cr
- |"LOC"|&no locale.library\cr
- |"REQ"|&no req.library\cr
- |"RT"|&no reqtools.library\cr
- |"GT"|&no gadtools.library (similar para las dem\'as)\cr
- \esptab
- (intuition/gadtools/asl/gfx)\cr
- \esptab
- |"WIN"|&fallo al abrir ventana\cr
- |"SCR"|&fallo al abrir pantalla\cr
- |"REQ"|&no se pudo abrir requester\cr
- |"FREQ"|&no se pudo abrir requester de ficheros\cr
- |"GAD"|&no se pudo crear gadget\cr
- |"MENU"|&no se pudo crear menu(s)\cr
- |"FONT"|&problema obteniendo fuente\cr
- \esptab
- (dos)\cr
- \esptab
- |"OPEN"|&no pude abrir fichero/fichero no existe\cr
- |"OUT"|&problemas escribiendo\cr
- |"IN"|&problemas leyendo\cr
- |"EOF"|&fin de fichero no esperado\cr
- |"FORM"|&error en formato de entrada\cr
- |"SEG"|&problemas con loadseg\cr
- \finsma
- \item{} La tendencia general es:
- \itemitem{*} todas las letras may\'usculas para excepciones generales del sistema,
- \itemitem{*} mezcladas para excepciones usadas por m\'as de una aplicaci\'on, pero
- no suficientemente generales,
- \itemitem{*} todas min\'usculas para excepciones lanzadas dentro varios m\'odulos de
- tu propia aplicaci\'on.
- \item{$-$} Todas los dem\'as, (incluyendo los IDs negativos) estan reservados.
- \endchapter\saltacap
- \beginchapter Cap\'{\i}tulo 14. Programaci\'on\\Orientada\\a Objetos
- Las caracter\'{\i}sticas que se describen en esta secci\'on est\'an agrupadas como
- tal ya que constituyen lo que generalmente se conoce como los tres
- principales componentes esenciales que hacen a un lenguaje 'Orientado a
- objetos' (es decir, herencia--ocultamiento de datos--polimorfismo). Sin
- embargo, en~E no son un {\it tema independiente} ya que cada uno de ellos se
- puede usar de todas formas junto con otras caracter\'{\i}sticas del~E.
- \seccion Herencia de Objetos.
- Siempre resulta inc\'omodo el no poder expresar dependencias entre |OBJECT|os, o
- reusar c\'odigo que funciona en un |OBJECT|o particular con otro mayor que
- encapsula al primero. La herencia de objetos en~E permite justamente hacer
- eso. Cuando tienes un objeto |a|:
- \ejemplos
- &|OBJECT a|\cr
- &\quad|sig, indice, term|\cr
- &|ENDOBJECT|\cr
- puedes crear un nuevo objeto |b| con las mismas propiedades de |a|
- (y compatible con el c\'odigo que se sirve de |a|):
- \ejemplos
- &|OBJECT b OF a|\cr
- &\quad|bla, x, burp|\cr
- &|ENDOBJECT|\cr
- y que equivale a:
- \ejemplos
- &|OBJECT b|\cr
- &\quad|sig, indice, term, /* de a */|\cr
- &\quad|bla, x, burp|\cr
- &|ENDOBJECT|\cr
- de forma que con |DEF p:b| podr\'as acceder directamente no s\'olo a |p.bla|
- sino tambi\'en a |p.sig|.
- \espacio
- Por ejemplo, si se tiene un m\'odulo con un |OBJECT|o para implementar un
- cierto tipo de datos con procedimientos de apoyo, (por ejemplo, una lista
- doblemente enlazada) se puede simplemente heredar de ella, a\~nadiendo datos
- propios al objeto, y usar las funciones {\sl existentes} para manipular la
- lista. Sin embargo la herencia s\'olo ofrece toda su potencia cuando se
- combina con m\'etodos.
- \seccion Ocultamiento de datos (|EXPORT/PRIVATE/PUBLIC|).
- E posee un mecanismo de ocultamiento de datos bastante controlable. Otros
- lenguajes, como el C++, usan el ocultamiento de datos en clases, lo cual nos
- lleva a la necesidad de trampas (como {\it friends}), y hace el ocultamiento de
- datos inseguro (Eiffel). El ocultamiento de datos de~E funciona a nivel de
- m\'odulos, lo cual permite modelar el ocultamiento de datos a nivel de clases,
- pero tambi\'en permite esquemas m\'as inteligentes.
- \espacio
- |PUBLIC| y |PRIVATE| declaran visible o no al mundo exterior una secci\'on
- de un objeto; en este caso, el mundo exterior es todo el c\'odigo ajeno al
- m\'odulo. Por otra parte, todo es visible para el c\'odigo del m\'odulo. Veamos un
- ejemplo:
- \begintt
- OBJECT misdatos PRIVATE -> todo el objeto es privado
- bla:PTR TO misdatos, burp, grrr:INT
- ENDOBJECT
- OBJECT aaargh
- blerk:PTR TO aaargh -> publico
- PRIVATE
- x:INT, y:INT, z:INT -> privado
- PUBLIC
- hmpf[10]:ARRAY OF misdatos -> publico de nuevo
- ENDOBJECT
- \endtt
- Un objeto es p\'ublico por omisi\'on, la aparici\'on de |PRIVATE| o |PUBLIC|
- actua como interruptor para la visibilidad del objeto en ese momento. En
- el primer objeto todo es privado. El segundo s\'olo tiene (x,y,z) como
- privado. Las palabras clave |PRIVATE| y |PUBLIC| pueden aparecer:
- \item{$-$} En la l\'{\i}nea de cabecera del objeto.
- \item{$-$} Como l\'{\i}nea en si misma dentro de la definici\'on del objeto.
- \item{$-$} Precediendo declaraciones en la definici\'on del objeto.
- \noin (es decir, pr\'acticamente en cualquier lugar)
- \Espacio
- {\it ?`Por que ocultamiento de datos?}
- \espacio
- Si quieres saber por qu\'e el ocultamiento de datos es una buena
- t\'ecnica, es probable que quieras leer alg\'un buen libro de OO\null{}. Pero en
- resumen: por lo general se supone que gran cantidad de los problemas de
- mantenimiento y mejora de fragmentos grandes de c\'odigo se deben al hecho
- de que resulta dificil cambiar las cosas, debido a que gran cantidad de
- c\'odigo empieza a depender de ciertas estructuras del c\'odigo. Si ocultas
- un objeto, s\'olo el c\'odigo dentro del m\'odulo depender\'a del formato de los
- objetos, y podr\'as modificar f\'acilmente la representaci\'on de un objeto y
- el c\'odigo que trabaja con \'el (por ejemplo, podr\'{\i}as cambiar f\'acilmente la
- implementaci\'on de una pila de |ARRAY| a una lista). Si gran parte del
- c\'odigo de una gran aplicaci\'on depende del hecho de que la pila es un
- |ARRAY|, no podr\'as cambiarlo con facilidad, lo cual acarrear\'a problemas. En
- resumen, intenta ocultar tanto como puedas sin llegar a ser demasiado
- restrictivo en el uso de tu objeto. El uso de m\'etodos te permitir\'a a
- menudo mantener todo el objeto privado.
- \seccion M\'etodos y m\'etodos virtuales.
- Un m\'etodo es muy parecido a un |PROC|, con la diferencia de que forma
- parte de un |OBJECT|o. Adem\'as, tambi\'en permite explotar el polimorfismo en
- los objetos, como veremos a continuaci\'on. Veamos la definici\'on de un m\'etodo:
- \ejemplos
- &|OBJECT blerk PRIVATE|\cr
- &\quad|x:PTR TO blerk, y:INT, z|\cr
- &|ENDOBJECT|\cr
- \Esptab
- &|PROC getx() OF blerk IS self.x|\cr
- la parte |OF blerk| le dice al compilador que pertenece al objeto |blerk|.
- F\'{\i}jate en que, aparte de |OF|, la sintaxis es completamente igual a la de un
- |PROC|, sin embargo, no se puede invocar como tal, y tambi\'en funciona de
- forma diferente.
- \espacio
- |self| es una variable local que est\'a disponible en todo m\'etodo, y es un
- puntero al objeto al que pertenece el m\'etodo (en este caso |self:PTR TO blerk|).
- Esta funci\'on s\'olo retorna el valor de campo |x| de |blerk|, lo cual
- tiene sentido, ya que esto te permite modificar m\'as tarde lo que representa |x|.
- \espacio
- Los m\'etodos se pueden llamar de forma similar a como se hace la selecci\'on de
- objetos ``|.|'':
- \ejemplos
- &|DEF a:PTR TO blerk|\cr
- &|NEW a|\cr
- &| ...|\cr
- &|a.getx() -> invoca metodo getx() en el objeto a|\cr
- en este ejemplo, sobre la invocaci\'on |a| toma el valor de |self| durante
- la jecuci\'on de |getx()|.
- \espacio
- Como ves, el uso de m\'etodos es interesante, aunque no hemos visto su
- poder real, el cual s\'olo aparece cuando se usa junto con la herencia.
- \espacio
- Si heredo un objeto que tiene m\'etodos, de forma autom\'atica obtengo
- esos m\'etodos en el nuevo objeto:
- \begintt
- OBJECT burp OF blerk PRIVATE -> como blerk, + campo extra
- prut:INT
- ENDOBJECT
- DEF b:PTR TO burp
- NEW b
- b.getx() -> mismo metodo
- \endtt
- \espacio
- Lo interesante viene ahora, ya que en lugar de heredar un m\'etodo,
- tambi\'en puedes redefinirlo:
- \ejemplos
- &|PROC getx() OF burp IS self.x+1|\cr
- (no hace falta decir que tambi\'en puedes a\~nadir nuevos m\'etodos)
- \espacio
- As\'{\i} que, cuando sea apropiado, puedes optar por modificar el
- funcionamiento de los m\'etodos que obtenemos de otros objetos, mientras
- que el interface a \'el (en este caso |getx()|) se mantiene igual. Esto no
- s\'olo permite la reutilizaci\'on del c\'odigo de forma selectiva, tambi\'en
- podemos hacer uso del polimorfismo:
- \ejemplos
- &|PROC hazalgo(o:PTR TO blerk)|\cr
- &| ...|\cr
- &| o.getx()|\cr
- &| ...|\cr
- &|ENDPROC|\cr
- \Esptab
- &|hazalgo(a)|\cr
- &|hazalgo(b)|\cr
- podemos llamar a este |PROC| tanto con |a| como con |b|, ya que ambos son
- compatibles con un objeto |blerk|. Aunque, ?`Cual de las dos implementaciones
- de |getx()| se invoca con |o.getx()|?\qquad Repuesta:\quad las dos. Las llamadas
- a m\'etodos en~E son lo que se llaman m\'etodos virtuales en otros lenguajes:
- act\'uan din\'amicamente en el tipo real del objeto (|o|) y llaman al m\'etodo
- apropiado.
- \espacio
- Un ejemplo m\'as claro:
- \ejemplos
- &|-> Ejemplo clasico de polimorfismo OO|\cr
- \esptab
- &|OBJECT loc|\cr
- &| PRIVATE posx:INT, posy:INT|\cr
- &|ENDOBJECT|\cr
- \esptab
- &|OBJECT punto OF loc|\cr
- &| PRIVATE color:INT|\cr
- &|ENDOBJECT|\cr
- \esptab
- &|OBJECT circulo OF punto|\cr
- &| PRIVATE rados:INT|\cr
- &|ENDOBJECT|\cr
- \esptab
- &|PROC muestra() OF loc IS WriteF('!`Soy una Localizacion!\n')|\cr
- &|PROC muestra() OF punto IS WriteF('!`Soy un Punto!\n')|\cr
- &|PROC muestra() OF circulo IS WriteF('!`Soy un Circulo!\n')|\cr
- \esptab
- &|PROC main()|\cr
- &| DEF x:PTR TO loc,l:PTR TO loc,p:PTR TO punto,c:PTR TO circulo|\cr
- &| ForAll({x},[NEW l,NEW p,NEW c],`x.muestra())|\cr
- &|ENDPROC|\cr
- aqu\'{\i} |x| es un |PTR TO loc|, por lo que podr\'{\i}as esperar que |x.muestra()|
- escribiera |!`Soy una Localizacion!| tres veces, pero en su lugar escribe la
- cadena correcta para cada objeto.
- \espacio
- Si quisieramos escribir esto en un lenguaje no OO, necesitar\'{\i}amos un
- |SELECT| para cada operaci\'on como |muestra()|, comprobando cierto valor
- presente en el objeto para ver de qu\'e tipo es. Si quisiera a\~nadir una
- nueva forma a las anteriores, como:
- \ejemplos
- &|OBJECT elipse OF circulo|\cr
- necesitar\'{\i}a cambiar todos los |SELECT|s a lo largo de la aplicaci\'on para
- que lo tengan en cuenta. Con el polimorfismo de objetos, simplemente
- escribir\'{\i}a un m\'etodo |muestra()|, y {\bf todo} el c\'odigo de la aplicaci\'on que
- llame a |x.muestra()| actuar\'{\i}a correctamente cuando |x| sea un |PTR TO elipse|,
- !`incluso sin tener que recompilar!
- \noin Es dificil mostrar el poder de esto en unos pocos ejemplos, la mejor
- forma de descubrirlo es us\'andolo en aplicaciones reales, y: como dije
- antes, leyendo un libro sobre ello.
- \Espacio
- {\it ?`C\'omo funciona el polimorfismo?}
- \noin En los ejemplos anteriores, est\'a claro que el compilador no sabe a qu\'e
- m\'etodo llamar\'a. Ese es el motivo por el cual~E usa un {\it objeto clase}, y
- cada objeto creado obtiene un puntero a este objeto. En el objeto clase
- se guarda toda la informaci\'on que es com\'un a todos los objetos de ese
- tipo, tales como punteros a m\'etodos. Cuando el compilador detecta una
- llamada como |x.muestra()|, en lugar de mirar directamente en la |muestra()|
- que pertenece al tipo de |x| (es decir |loc|), generar\'a c\'odigo que llama
- autom\'aticamente a la |muestra()| de punto, cuando |x| es realmente un objeto
- punto. Esto recibe a veces el nombre de enlace en tiempo de ejecuci\'on.
- \noin Los objetos que tienen m\'etodos son, por tanto, 4~bytes mayores de lo
- esperado, ya que contienen un puntero al objeto clase. El puntero lo
- inicializa autom\'aticamente |NEW|, raz\'on por la que {\it de momento} |NEW| es la
- \'unica forma de crear tales tipos de objetos.
- \espacio
- Si un m\'etodo se declara con el \'unico prop\'osito de permitir que las
- subclases lo redefinan (este tipo de clases se conocen en algunos
- lenguajes como clases bases virtuales), se puede usar |EMPTY|:
- \ejemplos
- &|PROC bla() OF obj IS EMPTY|\cr
- entonces se puede redefinir en las subclases. Dado que puede que el
- programador no implemente todos los m\'etodos de una vez, no es un error
- que se ejecute el m\'etodo anterior. Simplemente retornar\'a |0| o |NIL|.
- \espacio
- Se pueden a\~nadir m\'etodos a los |OBJECT|os del sistema:
- \ejemplos
- &|OBJECT migadget OF gadget -> !`de intuition!|\cr
- &| -> campos extra aqui|\cr
- &|ENDOBJECT|\cr
- &|PROC creategadget() OF migadget IS ...|\cr
- \finsma
- Un puntero a un objeto como \'este es compatible con el puntero normal a
- |gadget|, es decir, se puede a\~nadir directamente a un ventana, etc~\dots
- \seccion Constructores, Destructores y Super-M\'etodos.
- El constructor puede tener un nombre cualquiera, aunque suele darsele
- el mismo nombre que la clase. Incluso se pueden tener varios constructores
- para una misma clase. El constructor se llama directamente en un
- objeto creado con |NEW|:
- \ejemplos
- &|NEW obj.pila()|\cr
- \finsma
- Sin embargo, los destructores deben llamarse |end|. Y el objeto se
- destruye con:
- \ejemplos
- &|END obj|\cr
- y si |obj| tiene un m\'etodo |end()|, se le llama de forma autom\'atica. |end()|
- no debe tener argumentos, y no tiene sentido que retorne un valor.
- \Espacio
- El super-m\'etodo de un m\'etodo es el m\'etodo de su super-clase con el mismo
- nombre. Algunas veces es \'util llamar a este m\'etodo para incluir su
- comportamiento al de tu clases, sin embargo, debido a que lo has redefinido,
- el llamar al super-m\'etodo por su nombre simplemente se llamar\'{\i}a a s\'{\i} mismo.
- La palabra clave |SUPER| te permite llamar a cualquier m\'etodo de tu
- super-clase (o la super-clase de algun otro):
- \ejemplos
- &|SUPER obj.metodo()|\cr
- este fragmento de c\'odigo se puede usar como expresi\'on y como sentencia.
- Sin embargo, hay que tener cuidado, ya que si el superm\'etodo llama a otro
- m\'etodo de ese objeto, llamar\'a a la versi\'on redefinida, no la de su propio
- {\it nivel} (aunque eso suele ser lo que queremos). Adem\'as, el compilador
- mira el tipo est\'atico de |obj| para encontrar su superclase, no el tipo
- din\'amico (aunque pueda tener ese resultado).
- \endchapter\saltacap
- \beginchapter Cap\'{\i}tulo 15. Ensamblador\\en-l\'{\i}nea
- Como habr\'as apreciado en el ejemplo de Mnemot\'ecnicos ensamblador, las
- instrucciones en ensamblador se pueden mezclar libremente con c\'odigo~E\null{}.
- El gran secreto es que el compilador incluye un ensamblador completo.
- \espacio
- Adem\'as de los modos de direccionamiento normales del ensamblador, puedes
- usar los siguientes identificadores del E:
- \begintt
- mietiqueta
- LEA mietiqueta(PC),A1 /* etiquetas */
- DEF a /* variables */
- MOVE.L (A0)+,a /* fijate que <var> es <offset>(A4) (o A5) */
- MOVE.L dosbase,A6 /* identificadores de llamada a library */
- JSR Output(A6)
- MOVEQ #TRUE,D0 /* constantes */
- \endtt
- \espacio
- El ensamblador de |EC| permite las siguientes construcciones, en las cuales:
- \ejemplos
- \qquad $n$& = numregistro\cr
- \qquad $x$& = \'{\i}ndice\cr
- \qquad $lab$& = etiqueta, de: ``|etiqueta:|'' o ``|PROC etiqueta()|''\cr
- \qquad $abs$& = direcci\'on absoluta\cr
- \qquad $s$& = tama\~no. \enspace|L|, |W| o |B|, el que sea apropiado.\cr
- \finsma
- \item{$-$} modos de direccionamiento que permite |EC|:
- \itemitem{} |D|$n$, |A|$n$, |(A|$n$|)|, |(A|$n$|)+|, |-(A|$n$|)|, $x$|(A|$n$|)|, $x$|(A|$n$|,D|$n$|.|$s$|)|,
- $lab$|(PC)|, $lab$|(PC,D|$n$|.|$s$|)|, $abs$, $abs$|.W|\nota{escribe $abs$|.W| en
- hexadecimal, para no confundirlo con un valor real, es
- decir escribe |MOVE.L $4.W,A6|}
- \espacio
- \item{$-$} permitidos parcialmente:
- \itemitem{} |#|\<expconst>
- \espacio
- \item{$-$} no permitidos:
- \itemitem{} $lab$ (igual que $abs$), |#|$lab$
- \itemitem{} usa |LEA |$lab$|(PC),A|$n$ en su lugar.
- \espacio
- \item{$-$} modos extra:
- \itemitem{} \<var>|.|$s$ (transfiere contenido de \<var>.$s$ puede ser |.W| o |.B|,
- por omisi\'on es |.L|)
- \itemitem{} FuncionDeLibreria(A6)
- \espacio
- ejemplo:
- \begintt
- MOVE.W mivar.W,D0 -> mueve palabra baja de 'mivar'
- MOVE.L dosbase,A6
- JSR Write(A6)
- \endtt
- \espacio
- Adem\'as, E permite que las funciones retornen directamente un registro:
- \ejemplos
- &|ENDPROC D0|\cr
- y tambi\'en puedes interpretar esto c\'omo valores de retorno m\'utiples, es
- decir |D0/D1/D2|.
- \seccion El ensamblador en l\'{\i}nea comparado con un macro ensamblador.
- De alguna forma el ensamblador en-l\'{\i}nea se diferencia del macro-ensamblador
- de siempre, debido principalmente al hecho de que es una extensi\'on de~E, y
- por tanto sigue la sintaxis de~E\null{}. Las principales diferencias son estas:
- \espacio
- \item{$-$} los comentarios se hacen con |/* */| y no ``|;|'', y su significado es
- ligeramente distinto.
- \item{$-$} las palabras clave y los registros van en may\'usculas, todo depende de
- si va en may\'usculas o min\'usculas.
- \item{$-$} no hay macros ni otros lujos de los ensambladores (bueno, est\'a todo el
- lenguaje~E para cubrir esto~\dots)
- \item{$-$} debes tener en cuenta que los registros |A4/A5| no se deben ensuciar con
- el c\'odigo en ensamblador, ya que los utiliza el c\'odigo~E, si tu c\'odigo
- se puede llamar desde c\'odigo que reserva registros, debes preservar
- |D3-D7|. La siguiente instrucci\'on puede ayudar en caso de problemas:
- \itemitem{} |MOVEM.L D3-D7,-(A7); /*ensamblador en linea*/; MOVEM.L (A7)+,D3-D7|
- \item{$-$} {\bf Todavia} no se permite modelo |LARGE/hunk-reloc| en ensamblador. Esto
- quiere decir que de momento debes usar direccionamiento
- relativo a |PC| (que de todas formas es m\'as r\'apido).
- \seccion Utilizaci\'on de datos binarios (|INCBIN/CHAR...|).
- \Ejemplos
- \qquad Sintaxis:&|INCBIN |\<fichero>\cr
- incluye el fichero binario en el punto exacto de la sentencia, por tanto
- debe separase del c\'odigo. Por ejemplo:
- \ejemplos
- &|mitab: INCBIN 'df1:data/blabla.bin'|\cr
- \Espacio
- \ejemplos
- \qquad Sintaxis:&|LONG |\<valores>|, ...|\cr
- &|INT |\<valores>|, ...|\cr
- &|CHAR |\<valores>|, ...|\cr
- te permite colocar datos binarios directamente en el programa. Funciona
- como |DC.|$x$ en ensamblador. Se\~nalar que la sentencia |CHAR| tambi\'en recibe
- cadenas, y siempre estar\'an alineados a direcciones pares. Ejemplo:
- \ejemplos
- &|misdatos: LONG 1,2; CHAR 3,4,'!`Que hay amigos!',0,1|\cr
- \seccion OPT ASM.
- |OPT ASM| tambi\'en se discute en el apartado sobre |OPT|\null{}. Permite operar
- con |EC| como si fuera un ensamblador. No hay ninguna raz\'on para usar |EC|
- en lugar de otros macro-ensambladores, a excepci\'on de que es significativamente
- m\'as r\'apido que por ejemplo A68k, as\'{\i} como DevPac, y pierde con
- respecto a AsmOne (sniff |8-{|). Tambi\'en ser\'a tedioso el pasar los viejos
- discos con fuentes de Seka por |EC|, debido a las diferencias descritas con
- anterioridad. Si quieres escribir programas en ensamblador con |EC|, y
- quieres mantener tus fuentes compatibles con otros ensambladores, simplemente
- precede todos los elementos espec\'{\i}ficos de~E con un ``|;|'', |EC|~los
- usar\'a, y cualquier otro ensamblador los tomar\'a como comentarios. Empieza
- los comentarios normales con un smiley (|;->|). Por ejemplo:
- \ejemplos
- &|; OPT ASM|\cr
- &|comienzo: MOVEQ #1,D0 ;-> haz algo tonto|\cr
- &| RTS ;-> y sal|\cr
- esto lo ensamblar\'a cualquier ensamblador, incluyendo |EC|.
- \seccion Ensamblador en l\'{\i}nea y variables registro.
- Las variables registro son una buena ayuda al ensamblador en l\'{\i}nea, ya
- que funcionan como registros, aunque al mismo tiempo tienen un identificador
- claro en lugar de Dx, y adem\'as, el c\'odigo de E los guarda y recupera
- de forma autom\'atica. Por ejemplo:
- \ejemplos
- &|PROC bla()|\cr
- &| DEF count:REG|\cr
- &| MOVEQ #10,cuenta|\cr
- &|bucle: WriteF('cuenta=\d\n',cuenta)|\cr
- &| DBRA cuenta,bucle|\cr
- &|ENDPROC|\cr
- todas las instrucciones que funcionan con |Dx EA| funcionan con variables
- registro:
- \ejemplos
- &|MOVEQ #1,a|\cr
- &|MOVEM.L D0/D1/a/b/A0,-(A7)|\cr
- &|LSL.L a,b|\cr
- &| ....|\cr
- como se sabe, |EC| usa los registros |D3-D7| para estas variables registro.
- Si quieres escribir c\'odigo que mezcle libremente ensamblador con~E, es
- recomendable mantener variables usadas con frecuencia en variables registro, y
- temporales en |D0-D2|/|A0-A3|/|A5|.
- \endchapter\saltacap
- \beginchapter Cap\'{\i}tulo 16. Notas T\'ecnicas
- \seccion La palabra clave OPT.
- \Ejemplos
- \qquad Sintaxis:&|OPT |\<opciones>|, ...|\cr
- \finsma
- Te permite cambiar alg\'un funcionamiento del compilador:
- \smallskip
- \vbox{\halign{{\tt#}\hfil&
- \quad\vtop{\parindent=0pt\hsize=24pc\hangindent=0pt\strut#\strut}\cr
- LARGE&Fija el modelo de c\'odigo y datos en grande (|LARGE|). Por
- omisi\'on es peque\~no (|SMALL|); El compilador suele generar
- c\'odigo relativo a~|PC|, con un tama\~no m\'aximo de~32k. |LARGE|
- no pone tales l\'{\i}mites, y genera bloques (hunks) reloc.\cr
- STACK=x&Fija el tama\~no de la pila a |x|~bytes. \'Usalo siendo consciente de lo
- que haces. Normalmente el compilador hace una buena
- estimaci\'on del espacio de pila que se necesita.\cr
- ASM&Pone el compilador en modo ensamblador. A partir de ese
- momento s\'olo se permiten instrucciones en ensamblador,
- y no se genera c\'odigo de inicializaci\'on.\cr
- NOWARN&Elimina las advertencias. El compilador te avisar\'a si
- {\sl piensa} que tu programa es incorrecto, aunque sea
- sint\'acticamente correcto.\cr
- DIR=dirmodulos&Indica el directorio en el que el compilador buscar\'a los
- m\'odulos, por omisi\'on es |EMODULES:|.\cr
- OSVERSION=vers&Por omisi\'on es 33 (v1.2). Fija la versi\'on m\'{\i}nima de KickStart
- (como 37 para v2.04) bajo la que funcionar\'a tu
- programa. De esta forma, tu programa fallar\'a al abrir la
- dos.library en el c\'odigo de inicializaci\'on cuando tu
- c\'odigo se ejecuta en m\'aquinas anteriores. De todas
- formas, es de m\'as utilidad al usuario si compurebas la
- versi\'on t\'u mismo y das un mensaje de error apropiado.\cr
- MODULE&Indica que este c\'odigo es un m\'odulo.\cr
- EXPORT&Exporta autom\'aticamente las declaraciones del m\'odulo.\cr
- RTD&Genera RTDs en vez de RTS en fuente principal. S\'olo |020+|.\cr
- &({\it optimizaci\'on experimental\/})\cr
- 020,881,040&Genera c\'odigo para esa CPUs. Aun no utilizable.\cr
- REG=n&Usa |n| registros para reserva de registros.\cr
- \Ejemplos
- Ejemplo:&|OPT STACK=20000,NOWARN,DIR='df1:modules',OSVERSION=39,REG=3|\cr
- \finsma
- \seccion Modelo SMALL/LARGE.
- \E/ te permite elegir entre modelo de datos\b/c\'odigo |SMALL| y |LARGE|\null{}.
- F\'{\i}jate que la mayor\'{\i}a de los programas que escribir\'as (especialmente si
- acabas de empezar con~E) entrar\'an en~32KB al compilarlos: no tendr\'as que
- preocuparte de poner alg\'un modelo de generaci\'on de c\'odigo. Te dar\'as
- cuenta de la necesidad de un modelo |LARGE| tan pronto como |EC| empieze a
- quejarse de que ya no puede poner tu c\'odigo en~32KB\null{}. Para compilar un
- fuente con modelo |LARGE|:
- \ejemplos
- &|1> ec -l grande.e|\cr
- o mejor incluso, incluye la sentencia
- \ejemplos
- &|OPT LARGE|\cr
- al principio de tu c\'odigo.
- \seccion Organizaci\'on de la pila.
- Para guardar las variables locales y globales, el sistema en tiempo de
- ejecuci\'on de un ejecutable generado por AmigaE reserva un bloque de memoria,
- del cual tomar\'a una parte fija para almacenar todas las variables
- globales. El resto se usar\'a din\'amicamente seg\'un se vayan llamando las
- funciones. Cuando se llama a una funci\'on en~E, se reserva espacio en la
- pila para almacenar todos sus datos locales, el cual se libera al salir
- de la funci\'on. Ese es el motivo por el que tener arreglos grandes de
- datos locales puede se peligroso cuando se usa recursivamente: todos los
- datos de las llamadas anteriores a la misma funci\'on siguen estando en la
- pila y utilizan partes grandes del espacio libre de la pila. Sin
- embargo, si los procedimientos se llaman de una forma lineal, no hay
- motivo para que la pila se llene.
- \espacio
- El sistema en tiempo de ejecuci\'on siempre reserva 10k~extra por encima
- de esto para una recursi\'on normal (por ejemplo con arreglos locales
- peque\~nos) y buffers y espacio de sistema adicionales, por lo que
- reservar\'a 24k de espacio de pila.
- \seccion L\'{\i}mites fijos.
- \medskip
- \vbox{\halign{#\hfil&\quad#\hfil\cr
- \bartab
- OBJETO/ELEMENTO&TAMA\~NO/CANTIDAD/MAX\cr
- \bartab
- valor |CHAR|& $0\ldots 255$\cr
- valor |INT|& $-32$ Kb\dots $+32$ Kb\cr
- valor |LONG|/|PTR|& $-2$ Gb\dots $+2$ Gb\cr
- \Esptab
- logitud identificador& $100$ bytes$^\infty$\cr
- logitud l\'{\i}nea de c\'odigo& $2000$ tokens l\'exicos$^\simeq$\cr
- logitud c\'odigo& $2$ Gb (te\'oricamente)\cr
- listas constantes& algunos cientos de elementos$^\simeq$\cr
- cadenas constantes& $1000$ caracteres$^\infty$\cr
- anidamiento m\'aximo de bucles (|IF|, |FOR| etc.)&$500$ niveles\cr
- anidamiento m\'aximo de comentarios& $\infty$\cr
- \Esptab
- n\'umero de variables locales por procedimiento& $8000$\cr
- n\'umero de variables globales& $7500$\cr
- n\'umero de argumentos a funciones propias& $8000$ (junto con locales)\cr
- n\'umero argumentos funciones varargs de E (|WriteF()|)&$64$ (v2.1) / $1024$ (v2.5)\cr
- \Esptab
- un objeto (reservado local/global o din\'amico)& $8$ Kb\cr
- un arreglo, lista o cadena (local o global)& $32$ Kb\cr
- una cadena (din\'amicamente)& $32$ Kb\cr
- una lista (din\'amicamente)& $128$ Kb\cr
- un arreglo (din\'amicamente)& $2$ Gb\cr
- objetos con |NEW|& $64$ Kb elementos\cr
- |CHAR|/|INT|/|LONG| con |NEW|& $2$ Gb\cr
- \Esptab
- datos locales por procedimiento& $250$ Mb\cr
- datos globales& $250$ Mb\cr
- \Esptab
- tama\~no c\'odigo de un prodeciemiento& $32$ Kb\cr
- tama\~no c\'odigo del ejecutable& |SMALL| $32$ k, |LARGE| $2$ Gb\cr
- l\'{\i}mite pr\'actico actual (puede cambiar)& $2-5$ (v2.1) / $10$ Mb (v2.5)\cr
- \Esptab
- tama\~no buffer de c\'odigo generado e identific.& relativo al fuente\cr
- tama\~no buffer de etiquetas/saltos e intermed.& (re)reservado independ.\cr
- \bartab
- \espacio
- {\eightpoint
- \noin {$\simeq$} valor aproximado, depende de la situaci\'on.\par
- \noin {$\infty$} el valor no tiene l\'{\i}mite claro, pero este parece razonable.\par
- \seccion Mensajes de error, advertencias y comprobaci\'on de no referencia.
- \subsec Comprobaci\'on de no referencia. Al compilar tu c\'odigo fuente con |EC|,
- algunas veces obtienes un mensaje del tipo:
- \ejemplos
- &|UNREFERENCED: |\<ident>, \<ident>|, ...|\cr
- que aparece cuando declaras variables, funciones o etiquetas, y luego no
- las usas. Este servicio extra que te ofrece el compilador te puede dar
- alguna buena pista sobre todos esos errores dif\'{\i}ciles de detectar.
- \subsec Advertencias. Suelen indicar cosas que pueden ir mal, aunque realmente
- no es un error.
- \adver 'A4/A5 used in inline assembly'
- 'A4/A5 usado en ensamblador en l\'{\i}nea'
- Esta es la advertencia que obtendr\'as cuando usas los registros A4 o A5
- en tu c\'odigo ensamblador. El motivo de esto es que esos registros los
- usa E internamente para direccionar las variables globales y locales
- respectivamente. Por supuesto, puede haber una buena raz\'on para
- utilizarlos, como hacer un |MOVEM.L A4/A5,-(A7)| antes de una parte
- grande de ensamblador en l\'{\i}nea.
- \adver 'keep an eye on your stacksize'
- 'hecha un ojo al tama\~no de la pila'
- \fadver
- \adver 'stack is definitely too small'
- 'la pila es definitivamente muy peque\~na'
- Ambas pueden ser provocadas por el uso de |OPT STACK=|\<tama\~no>. El
- compilador simplemente contrastar\'a tu \<tama\~no> con su {\it estimaci\'on}, y
- escribir\'a la primera advertencia si piensa que est\'a bien aunque un poco
- ajustado, y la \'ultima si probablemente es muy peque\~no.
- \adver 'suspicious use of |"="| in void expressions (s). (line \%d)'
- 'uso sospechoso de |"="| en expersiones void (s). (l\'{\i}nea \%d)'
- Esta advertencia aparece si escribes expresiones como |a=1| como una
- sentencia. La raz\'on de esto es que una comparaci\'on no tiene mucho
- sentido como sentencia, aunque la raz\'on principal es que puede ser
- motivo del frecuente error tipogr\'afico de |a:=1|. Puede ser dificil de
- encontrar el olvido de ``|:|'', y puede tener consecuencias desastrosas.
- \adver 'module changed |OPT| settings'
- 'el m\'odulo cambi\'o las opciones |OPT|'
- Si usas un m\'odulo que usa |OPT OSVERSION=37|, \'esta tambi\'en afectar\'a al
- programa principal. La advertencia te avisa de \'esto. Para eliminarla
- s\'olo tienes que poner un |OPT| del mismo tipo en el programa principal.
- \adver 'variable used as function'
- 'variable usada como funci\'on'
- En v3, cualquier variable se puede usar como una funci\'on. Esta
- advertencia est\'a para {\it avisarte} por si lo haces de forma accidental.
- \adver 'code outside |PROC|s'
- 'c\'odigo fuera de |PROC|s'
- Has escrito c\'odigo entre |PROC|s, lo cual es de rara utilidad.
- \Espacio
- \subsec Errores.
- El compilador escribir\'a la l\'{\i}nea de c\'odigo fuente que caus\'o el error a
- continuaci\'on de \'este, y un cursor en el punto exacto del error. El cursor
- denota el punto en el que se hallaba el compilador cuando {\it descubri\'o}
- el error, por lo que parece l\'ogico pensar que el s\'{\i}mbolo que provoc\'o el
- error es el que est\'a justo {\it antes} del cursor.
- \parindent=4em
- \error 'Sintaxis error'
- 'Error de sintaxis'
- El error m\'as com\'un. Este error aparece tanto cuando no hay otro error
- apropiado, como cuando la estructura de tu c\'odigo es demasiado anormal.
- \error 'unknown keyword/const'
- 'palabra clave/constante desconocida'
- Has utilizado un identificador en may\'usculas (como |IF| o |TRUE|), y el
- compilador no pudo encontrar una definici\'on de \'el. Causas:\hfil\break
- $\bullet$ palabra clave mal escrita\hfil\break
- $\bullet$ usaste una constante, pero olvidaste definirla en una sentencia |CONST|\hfil\break
- $\bullet$ te olvidaste de indicar el m\'odulo en el que se define la constante
- \error '|":="| expected'
- 'se esperaba |":="|'
- Has escrito una sentencia |FOR| o de asignaci\'on, y pusiste otra cosa
- diferente de |:=| en su lugar.
- \error 'unexpected characters in line'
- 'caracteres en la l\'{\i}nea no esperados'
- Usaste caracteres que no tienen significado sint\'actico fuera de una
- cadena. Por ejemplo: |@!&\~|
- \error 'label expected'
- 'se esperaba una etiqueta'
- En algunos puntos, por ejemplo despu\'es de la palabra clave |PROC| o |JUMP|, se
- pide un identificador de etiqueta, y escribiste algo diferente.
- \error '|","| expected'
- 'se esperaba |","|'
- Al especificar una lista de elementos (por ejemplo una lista de
- par\'ametros), escribiste algo que no era una coma.
- \error 'variable expected'
- 'se esperaba una variable'
- Por ejemplo en:\qquad|FOR |\<var>|:= ...| etc.
- \error 'value does not fit in 32 bit'
- 'el valor no entra en 32 bits'
- Al especificar una constante diste un n\'umero demasiado grande, como:
- \quad|$FFFFFFFFF|, |"abcdef"|. Tambi\'en ocurre cuando defines un |SET|
- con m\'as de 32~elementos.
- \error 'missing apostrophe/quote'
- 'falta ap\'ostrofe/comilla'
- Te olvidaste del |'| al final de una cadena.
- \error 'incoherent program structure'
- 'estrutura de programa incoherente'
- $\bullet$ empezaste un nuevo PROC antes de acabar el anterior,\hfil\break
- $\bullet$ no anidas los bucles correctamente, por ejemplo:\hfil\break
- \null\qquad\qquad|FOR|\hfil\break
- \null\qquad\qquad| IF|\hfil\break
- \null\qquad\qquad| ENDFOR|\hfil\break
- \null\qquad\qquad|ENDIF|
- \error 'illegal command-line option'
- 'opci\'on de l\'{\i}nea de comandos ilegal'
- Al especificar |'EC -opt fuente'| escribiste algo para |-opt| que no es
- una opci\'on legal de~|EC|.
- \error 'division and multiplication 16bit only'
- 'divisi\'on y multiplicaci\'on s\'olo con 16 bits'
- El compilador detect\'o que estabas a punto de usar 32 bits para |*| o |/|.
- Lo cual no tendr\'{\i}a el resultado deseado en tiempo de ejecuci\'on.
- \error 'superfluous items in expression/statement'
- 'elementos superfluos en expresi\'on/sentencia'
- Despu\'es de haber compilado tu sentencia, el compilador a\'un encontr\'o
- tokens l\'exicos en vez del final de l\'{\i}nea. Es probable que te hallas
- olvidado del \<|lf|> o ``|;|'' para separar dos sentencias.
- \error 'procedure |"main"| not available'
- 'no se dispone del procedimiento |"main"|'
- !`Tu programa no incluye un procedimiento |main()|!
- \error 'double declaration of label'
- 'doble declaraci\'on de una etiqueta'
- Declaraste una etiqueta dos veces, por ejemplo:\qquad|etiqueta:|\quad y\quad|PROC etiqueta()|
- \error 'unsafe use of |"*"| or |"/"|'
- 'uso de |"*"| o |"/"| no seguro'
- De nuevo relacionado con el hecho de que los operadores |*| y |/| son de 16 bits, y no de 32.
- Mira 'divisi\'on y multiplicaci\'on s\'olo con 16 bits'.
- \error 'reading sourcefile didn{'}t succeed'
- 'sin \'exito al leer el fichero fuente'
- Comprueba la especificaci\'on de fichero fuente que diste con |ec mifuente|,
- aseg\'urate de que acaba en |.e|\nota{en la versi\'on actual del compilador
- ya no es necesario poner la extensi\'on.}
- \error 'writing executable didn{'}t succeed'
- 'sin exito al escribir el ejecutable'
- Al escribir el c\'odigo generado como ejecutable produjo un error de DOS\null{}.
- Por ejemplo, el ejecutable que ya exist\'{\i}a no se pudo reescribir.
- \error 'no args'
- 'faltan argumentos'
- |USAGE: ec [-opts] <sourcecodefilename> (`.e' is added)|\hfil\break
- |USO: ec [-opts] <nombrefichfuente> (se a\~nade `.e')|\hfil\break
- Obtienes esto simplemente con escribir |ec| sin ning\'un argumento.
- \error 'unknown/illegal addressing mode'
- 'modo de direccionamiento desconocido/ilegal'
- Este error s\'olo es del ensamblador en l\'{\i}nea. Las posibles causas son:\hfil\break
- $\bullet$ usaste alg\'un tipo de direccionamiento que no existe en el 68000\hfil\break
- $\bullet$ el modo de direccionamiento existe, pero no para esa instrucci\'on. No
- todas las instrucci\'ones en ensamblador permiten todas las combinaciones
- de direcci\'on efectiva tanto para origen como destino.
- \error 'unmatched parentheses'
- 'discordancia de par\'entesis'
- Tu sentencia tienen m\'as ``|(|'' que ``|)|'' o la rev\'es.
- \error 'double declaration'
- 'declaraci\'on doble'
- Un identificador se usa en dos o m\'as declaraciones.
- \error 'unknown identifier'
- 'identificador desconocido'
- Un identificador no se usa en ninguna declaraci\'on; es desconocido.
- Probablemente te olvidaste de ponerlo en una sentencia |DEF|.
- \error 'incorrect \#of args or use of |()|'
- 'n\'umero de args o uso de |()| incorrecto'
- $\bullet$ Te olvidaste poner ``|(|'' o ``|)|'' en el punto correcto,\hfil\break
- $\bullet$ pasate un n\'umero de argumentos incorrecto a alguna funci\'on.
- \error 'unknown e/library function'
- 'funci\'on de E/de biblioteca desconocida'
- Utilizas un identificador con el primer caracter en may\'uscula y segundo
- en min\'uscula, pero el compilador no le encontr\'o ninguna definici\'on.
- Posibles causas:\hfil\break
- $\bullet$ Nombre de funci\'on m\'al escrito.\hfil\break
- $\bullet$ Se te olvid\'o incluir el m\'odulo que define esa llamada.
- \error 'illegal function call'
- 'llamada ilegal a funci\'on'
- Raramente aparece. Puede aparecer si intentas construir llamadas a
- extra\~nas, como |WriteF()|s anidados. \ Ejemplo:\qquad|WriteF(WriteF('!`hola!'))|
- \error 'unknown format code following $\backslash$'
- 'c\'odigo de formato que sigue a $\backslash$ desconocido'
- Especificaste un c\'odigo de formato ilegal en una cadena.
- \error '|/*| not properly nested comment structure |*/|'
- '|/*| estrutura de comentarios incorrectamente anidada |*/|'
- N\'umero de |/*| no es igual al de |*/|, o est\'an en orden inapropiado.
- \error 'could not load binary'
- 'no he podido leer binario'
- No se pudo leer \<especfichero> en |INCBIN |\<especfichero>.
- \error '|"|$\}$|"| expected'
- 'se esperaba |"|$\}$|"|'
- Empezaste una expresi\'on con |{|\<var>, pero se te olvid\'o el |}| final.
- \error 'immediate value expected'
- 'se esperaba un valor inmediato'
- Algunas construcciones requieren un valor inmediato en lugar de una
- expresi\'on. Por ejemplo:\hfil\break
- \null\qquad\qquad|DEF s[x*y]:STRING -> mal: s\'olo es legal algo como s[100]:STRING|
- \error 'incorrect size of value'
- 'tama\~no de valor incorrecto'
- Especificaste un valor inaceptablemente grande (o peque\~no) para alguna
- construcci\'on. Ejemplos:\hfil\break
- \null\qquad\qquad|DEF s[-1]:STRING, t[1000000]:STRING /* debe ser 0..32000 */|\hfil\break
- \null\qquad\qquad|MOVEQ #1000,D2 /* debe ser -128..127 */|
- \error 'no e code allowed in assembly modus'
- 'no se permite c\'odigo E en modo ensamblador'
- Pusiste el compilador en modo ensamblador con |OPT ASM|, pero por
- accidente escribiste algo de c\'odigo en~E.
- \error 'illegal/inappropriate type'
- 'tipo ilegal/no apropiado'
- En alg\'un lugar donde se necesitaba una especificaci\'on \<tipo> escribiste
- algo no apropiado. Ejemplos:\hfil\break
- \null\qquad\qquad|DEF a:PTR TO ARRAY /* no hay tal tipo */|\hfil\break
- \null\qquad\qquad|[1,2,3]:STRING|
- \error '|"]"| expected'
- 'esperaba |"]"|'
- Empezaste con |[| pero nunca lo acabaste con |]|.
- \error 'statement out of local/global scope'
- 'sentencia fuera del alcance local/global'
- Un punto de ruptura del alcance es la primera sentencia |PROC|\null{}. Antes de
- ella s\'olo se permiten definiciones globales (|DEF|,|CONST|,|MODULE|,etc.), no
- c\'odigo. En la segunda parte s\'olo son legales c\'odigo y definiciones de
- funciones, no definiciones globales.
- \error 'could not read module correctly'
- 'no se pudo leer el m\'odulo correctamente'
- Ocurri\'o un error DOS intentando leer un m\'odulo en una sentencia |MODULE|\null{}.
- Causas:\hfil\break
- $\bullet$ |EModules:| no ha sido asignado correctamente.\hfil\break
- $\bullet$ Nombre del m\'odulo escrito de forma incorrecta, o no existe.\hfil\break
- $\bullet$ Escribiste |MODULE 'bla.m'| en lugar de |MODULE 'bla'|.
- \error 'workspace full!'
- '!`espacio de trabajo lleno!'
- Raras veces aparece. Si lo hace, deber\'as usar la opci\'on ``|-m|'' (|ADDBUF|)
- para forzar a~|EC| a que haga una estimaci\'on superior de la cantidad de
- memoria que necesita. Intenta compilar con |-m2|, luego con |-m3|,~\dots,
- hasta que desaparezca el error. Es probable que hayas escrito una
- aplicaci\'on enorme con cantidades de datos gigantes antes de poder tener la
- oportunidad de obtener este error.
- \error 'not enough memory while (re-)allocating'
- 'memoria no suficiente al (re-)reservar'
- Simplemente eso. Posibles soluciones:\hfil\break
- |1. |Estabas corriendo otros programas en multitarea. Aband\'onalos e
- intentalo de nuevo.\hfil\break
- |2. |Ten\'{\i}as, poca memoria y tu memoria estaba
- fragmentada. Prueba reiniciando el sistema.\hfil\break
- |3. |Ninguna de |1-2|. Compra una expansi\'on de memoria (ejem!).
- \error 'incorrect object definition'
- 'definci\'on de objeto incorrecta'
- Escribiste alguna torpeza en las definiciones entre |OBJECT| y |ENDOBJECT|.
- \error 'illegal use of/reference to object'
- 'uso ilegal de/referencia a objeto'
- Si usas expresiones como |ptr.miembro|, |miembro| debe ser un miembro legal
- del objeto al que apunta |ptr|.
- \error 'incomplete |IF THEN ELSE| expression'
- 'expresi\'on |IF THEN ELSE| incompleta'
- Si usas |IF| como operador, la parte |ELSE| es imprescindible: una expresi\'on
- con un |IF| en ella siempre necesita retornar un valor, mientras que una
- sentencia con un |IF| en ella puede, simplemente, no hacer nada si no
- est\'a presente una parte |ELSE|.
- \error 'unknown object identifier'
- 'identificador de objeto desconocido'
- Usaste un identificador reconocido por el compilador como parte de
- alg\'un objeto, pero se te olvid\'o declararlo. Motivos:\hfil\break
- $\bullet$ nombre mal escrito\hfil\break
- $\bullet$ falta el m\'odulo\hfil\break
- $\bullet$ el identificador del m\'odulo no se escribe como esperas de los RKRMs.
- Compruebalo con |ShowModule|. Tienes que tener en cuenta que el sistema
- de objetos del Amiga se hereda de los identificadores del ensamblador,
- no del~C\null{}. Y adem\'as siguen la sintaxis de~E.
- \error 'double declaration of object identifier'
- 'redeclaraci\'on de identificador de objeto'
- Se usa un mismo identificador en la definici\'on de dos objetos.
- \error 'reference(s) out of 32k range: switch to |LARGE| model'
- 'referencia(s) fuera del rango de 32k: cambia a modelo |LARGE|'
- S\'olo tienes que poner |OPT LARGE| en tu c\'odigo fuente y seguir.
- \error 'reference(s) out of 256 byte range'
- 'referencia(s) fuera del rango de 256 bytes'
- Es probable que hayas escrito un |BRA.S| o |Bcc.S| a gran distancia.
- \error 'too sizy expression'
- 'expresi\'on muy grande'
- Usaste cadenas |''| o listas |[]|, quizas |[[]]| recursivas, de gran tama\~no.
- \error 'incomplete exception handler definition'
- 'definici\'on de manejador de excepciones incompleto'
- Probablemente usaste |EXCEPT| sin |HANDLE|, o al rev\'es.
- \error 'not allowed in a module'
- 'no permitido en un m\'odulo'
- Estas haciendo una de las pocas cosas que no se pueden hacer en un
- m\'odulo, como son variables globales con inicializaci\'on.
- \error 'allowed in modules only'
- 's\'olo se permite en m\'odulos'
- Es probable que hayas usado |EXPORT| en tu c\'odigo fuente principal.
- \error 'this doesn{'}t make sense'
- 'esto no tiene sentido'
- Error general.
- \error 'you need a newer version of |EC| for this |:-)|'
- 'necesitas una versi\'on m\'as reciente de |EC| para esto |:-)|'
- Es probable que estes usando un m\'odulo que fue compilado con una
- versi\'on m\'as reciente de la que tienes.
- \error 'no matching |"["|'
- '|"["| sin emparejar'
- Se encontr\'o un |]| en una sentencia sin un |[| que lo empareja.
- \error 'this instruction needs a better |CPU/FPU| (see |OPT|)'
- 'esta instrucci\'on necesita una |CPU/FPU| mejor (mira |OPT|)'
- Usas una construcci\'on (probablemente una instrucci\'on en ensamblador) que
- requiere un |OPT 020| o parecido.
- \error 'object doesn{'}t understand this method'
- 'el objeto no entiende este m\'etodo'
- Invocaste un m\'etodo que no fu\'e definido para ese objeto.
- \error 'method doesn{'}t have same \#of args as method of baseclass'
- 'el m\'etodo no tiene el mismo n\'umero de args que el de la clase base'
- Si redefines un m\'etodo, debes asegurarte de que el nuevo tiene el
- mismo n\'umero de argumentos que el original.
- \error 'too many register variables in this function'
- 'demasiadas variables registro en esta funci\'on'
- Estas declarando variables resgitro con |:REG|, y de momemto
- no se pueden usar m\'as de |5|.
- \error 'Linker can{'}t find all symbols'
- 'el enlazador no encuentra todos los s\'{\i}mbolos'
- Si usas un m\'odulo $A$ que usa a su vez un m\'odulo $B$, $B$ tambi\'en debe ser
- enlazado. $A$ depende de ciertos |PROC|s que estan en $B$, y si $B$ fue
- recompilado sin esos |PROC|s, entonces el enlazador tendr\'a problemas al
- crear tu ejecutable.
- \error 'could not open |"mathieeesingbas.library"|'
- 'no pude abrir |"mathieeesingbas.library"|'
- Si usas c\'odigo con reales, el propio compilador necesitar\'a funciones de
- reales para poder generar el c\'odigo.
- \error 'illegal destructor definition'
- 'definici\'on de desctructor ilegal'
- Definiste un m\'etodo |end()| con argumentos (o con valor de retorno).
- \error 'implicit initialisation of private members'
- 'inicializaci\'on impl\'{\i}cita de miembros privados'
- Escribiste una expresi\'on |[...]| o |NEW [...]| que tiene partes privadas.
- \error 'double method declaration'
- 'redefinici\'on de m\'etodo'
- Definiste un m\'etodo dos veces para el mismo objeto.
- \error 'object referenced by other object not found'
- 'objeto hace referencia a otro que no se encuentra'
- Es probable que heredaras de alg\'un otro objeto en otro m\'odulo, y lo
- cambiaste (por ejemplo su nombre) sin cambiar\b/recompilar los dem\'as
- m\'odulos que dependen de \'el tambi\'en.
- \error 'unknown preprocessor keyword'
- 'palabra clave de preprocesador desconocida'
- El preprocesador de |EC| s\'olo reconoce |#define|, |#ifdef|, |#ifndef| y |#endif|.
- \error 'illegal macro definition'
- 'definici\'on de macro ilegal'
- Provocaste un error de sintaxis al escribir tu |#define|.
- \error 'incoherent \#|ifdef|/\#|ifndef| nesting'
- 'anidamiento de \#|ifdef|/\#|ifndef| no coherente'
- Se te olvid\'o cerrar con |#endif|, o algo parecido.
- \error 'macro redefinition'
- 'redefinici\'on de macro'
- No puedes usar el mismo identificador de nombre de macro dos veces.
- \error 'Sintaxis error in \#|ifdef|/\#|ifndef|/\#|else|/\#|endif|'
- 'error de sintaxis en \#|ifdef|/\#|ifndef|/\#|else|/\#|endif|'
- ({\it mira el apartado sobre la correcta compilaci\'on de c\'odigo condicional\/}).
- \error 'macro(s) nested too deep'
- 'macro(s) anidada(s) a un nivel muy profundo'
- Obtendr\'as esto si tienes macros que se expanden a otras, las cuales se
- expanden a otras,~\dots, de forma que la cantidad de memoria necesaria
- para esto se empieza a desmadrar. Lo m\'as seguro es que hayas definido
- una macro recursiva (que intentar\'a expandirse indefinidamente).
- \error 'method definition out of object/module scope'
- 'definci\'on de m\'etodo fuera del alcance del objeto/m\'odulo'
- S\'olo puedes definir m\'etodos para un objeto en el mismo m\'odulo\b/fuente en
- el que se define el objeto.
- \parindent=2em
- \seccion Organizaci\'on del buffer del compilador y reserva.
- Es \'util saber como organiza |EC| sus buffers, cuando obtienes un error
- de {\ninebf 'workspace full'} (raras veces), o quieres saber qu\'e es lo que sucede
- realmente cuando se compila tu programa.
- \espacio
- Un compilador, y en este caso |EC|, necesita buffers para mantener todo
- tipo de cosas, como identificadores, etc~\dots, y necesita un buffer para
- almacenar el c\'odigo que genera. |EC| desconoce el tama\~no que deben tener
- esos buffers. Esto no representa ning\'un problema para la mayor\'{\i}a de los
- buffers, como el que se utiliza para varias estructuras, si el buffer se
- llena durante la compilaci\'on, |EC| s\'olo tiene que reservar un nuevo fragmento
- de memoria y continuar. Sin embargo, otros buffers, como el que
- contiene el c\'odigo generado, debe estar en un bloque de memoria cont\'{\i}guo
- que no cambien durante la compilaci\'on: |EC| necista hacer una buena estimaci\'on
- sobre el tama\~no de este buffer para poder compilar c\'odigo fuente ya
- sea grande o peque\~no. Para ello |EC| calcula la memoria que necesitar\'a
- dependiendo del tama\~no del c\'odigo fuente, y le suma una cantidad
- apropiada. De esta forma, en el 99\%~de los casos, |EC| habr\'a reservado
- suficiente memoria para compilar practicamente cualquier c\'odigo fuente,
- en los dem\'as casos, se te ofrecer\'a un error y tendr\'as que especificar m\'as
- memoria con la opci\'on |-m| (|ADDBUF|).
- \espacio
- Para ver c\'omo funciona esto en la pr\'actica prueba con fuentes de diferentes
- tipos y tama\~nos en combinaci\'on con la opci\'on |-b| (|SHOWBUF|).
- \seccion Reserva de registros.
- E v3 permite la reserva de registros, que es una t\'ecnica para mantener
- variables en registros en lugar de la pila. En c\'odigo normal que use
- rutinas del~SO no notar\'as mucho la diferencia, aunque para bucles de
- computaci\'on peque\~nos, esta optimizaci\'on puede marcar una gran diferencia.
- \espacio
- Hay dos formas de utilizar reserva de registros:
- \item{$-$} Con la opci\'on |REG|.
- \item{} Si, por ejemplo, escribes |EC REG=3 bla.e|, (de momento max=5), |EC|
- buscar\'a para cada |PROC| las tres variables m\'as usadas y las pondr\'a en
- registros. La resreva de registro es una t\'ecnica que intenta ser
- inteligente: calcular\'a un peso para cada variable, y usar\'a heur\'{\i}sticos
- para incrementar tal peso, por ejemplo, una variable usada en un bucle
- |FOR| obtiene un peso relativamente mayor que una usada fuera de \'el, y
- una en un |IF| obtendr\'a un peso incluso menor. Estos pesos se combinan,
- de forma que un |WHILE| en un |FOR| obtiene un peso bastante mayor.
- \item{$-$} HTM (Hazlo Tu Mismo).
- \item{} Puedes poner la palabra clave |REG| delante de cualquier tipo en una
- declaraci\'on, por ejemplo:
- \itemitem{} |DEF x:REG, s[4]:REG LIST|
- \item{} puedes utilizarlo si no crees en el reservador de registros, o si quieres
- realizar un ajuste fino en un s\'olo |PROC|\null{}. Incluso puedes usar las
- dos t\'ecnicas juntas: si en un |PROC| tienes una variable con |:REG|, compilar
- con |REG=5| permitir\'a a~|EC| repartir los 4~restantes por s\'{\i} mismo.
- \Espacio
- Por omisi\'on |REG=0|, haciendo que |EC| opere como en versiones anteriores.
- \espacio
- S\'olo se {\bf pueden} reservar variables locales que no son par\'ametros.
- Ademas, si tomas la direcci\'on de una variable con |{}|, no la puedes poner
- en un registro (adivina por qu\'e). No se pueden reservar registros en
- |PROC|s que tienen manejador de excepciones, de momento.
- \Espacio
- Estas son algunas cosas a tener en cuenta al usar registros:
- \item{$-$} Esta parte de |EC| (E v3.0a) se ha comprobado ser bastante fiable, pero
- debes seguir comprobando que el funcionamiento sea igual que en c\'odigo
- sin reserva.
- \item{} {\sl Debe} funcionar bien, pero es demasiado pronto para garantizarlo |:-)|
- Resumiendo: desde este momento, ten cuidado al aplicar estas t\'ecnicas.
- \item{$-$} |EC| usa los registros |D7...D3| para variables, de modo que si usas
- ensamblador en l\'{\i}nea, debes procurar que los |PROC|s que usan reserva de
- registros o |:REG| no los ensucien. El c\'odigo generado por un |PROC|
- guarda de forma autom\'atica los registros que usa para proteger el
- c\'odigo desde el que fu\'e llamado.
- \item{$-$} Pista: compilar con |REG=5| no tiene porqu\'e ser m\'as r\'apido, ya que el
- guardar las variables en llamadas a funci\'on\b/librer\'{\i}a implica m\'as c\'odigo
- a ejecutar. Adem\'as, si {\it todo} el c\'odigo en cuesti\'on opera con llamadas
- de librer\'{\i}a en lugar de computaci\'on pura, no esperes ninguna ventaja
- con los registros.
- \begintt
- PROC main() -> este programa sera dos veces mas rapido
- DEF a,b=10,c=20,d -> facilmente si se reservan registros.
- FOR a:=1 TO 1000000 DO d:=b+c
- ENDPROC
- PROC main() -> este sera, como mucho, un 5% mas rapido
- DEF a,s[100]:STRING,t -> reservando registros.
- t:='poner "a" en un reg no creo que acelere esto mucho.'
- FOR a:=1 TO 100000 DO StrCopy(s,t)
- ENDPROC
- \endtt
- \endchapter\saltacap
- \beginchapter Cap\'{\i}tulo 17. Utilidades\\imprescindibles
- \seccion bin/showmodule.
- Como ya habr\'as notado, el equivalente de~E para los {\sl includes\/}\nota{ficheros de cabecera},
- los m\'odulos, son ficheros binarios, muy parecidos a los que se ofrecen con
- los compiladores de Modula2 por ejemplo. Para ver el contenido de tales
- ficheros en forma \ASCII/ legible, puedes utilizar |ShowModule|:
- \ejemplos
- &|ShowModule |\<especmodulo>\cr
- \Ejemplos
- Ejemplos:&|1> showmodule EModules:intuition/intuition|\cr
- &|1> showmodule >gadtools.txt EModules:gadtools|\cr
- Por omisi\'on |ShowModule| escribe a |stdout|, y se puede
- detener en cualquier momento con \<|CtrlC|>.
- \seccion sources/utilities/showhunk{.}e, bin/showhunk.
- Muestra todo tipo de ficheros ejecutables, adem\'as de ficheros
- objeto |.o| generados por (otros) compiladores\b/ensambladores. Muestra la
- estructura (muy simple) de los ejecutables generados por~|EC|, aunque
- tambien permite ficheros overlay complejos. Tambi\'en muestra las etiquetas
- (como |XREF|s y |XDEF|s). Y lo m\'as importante de todo, |ShowHunk| ofrece
- un desensamblador para los bloques de c\'odigo, usando la opci\'on |DISASM/S|.
- \ejemplos
- &|ShowHunk |\<ficheroeje>\cr
- \Ejemplos
- Ejemplos:&|1> ShowHunk holamundo|\cr
- &|1> ShowHunk DISASM dpaint|\cr
- \seccion bin/iconvert, bin/pragma2module.
- Estas dos utilidades son s\'olo para programadores de~E avanzados\nota{al igual
- que la utilidad |ShowModule|, ya no se incluye el c\'odigo
- fuente de estas utilidades en la distribuci\'on, ya que la gente utilizaba
- de forma incorrecta su conocimiento del formato de los m\'odulos |.m|.
- Es {\bf privado}. Contacta conmigo primero si quieres hacer algo con \'el.}.
- S\'altate este apartado si crees que (todav\'{\i}a) no eres uno de ellos.
- \espacio
- |IConvert| convierte definiciones de estructuras y constantes de los
- ficheros |.i| en ensamblador a m\'odulos~E, y |Pragma2Module| hace lo mismo
- con ficheros |pragma| de SAS/C de definici\'on de librer\'{\i}a. Por supuesto, ya
- se han convertido de esta forma todos los includes de Commodore, pero
- digamos que encuentras una librer\'{\i}a de PD que te gustar\'{\i}a usar con~E,
- entonces necesitar\'as estas utilidades.
- \espacio
- La mayor\'{\i}a de las librer\'{\i}as vienen con varios includes definiendo,
- obviamente, las llamadas a librer\'{\i}a de la librer\'{\i}a, as\'{\i} como constantes
- y estructuras (|OBJECT|os en~E) que utiliza. Digamos que se llama
- |tools.library|, entonces, es probable que incluya:
- \ejemplos
- &|pragmas/tools_pragmas.h|\cr
- &|includes/tools.i|\cr
- entonces tienes que hacer:
- \ejemplos
- &|1> Pragma2Module tools_pragmas.h|\cr
- renombrar el |tools_pragmas.m| resultante a |tools.m| y ponerlo en
- |EModules:|, luego comprueba con |ShowModule| si todo fue correcto. Despu\'es de esto
- ya puedes usar la |tools.library| en tu programa:
- \ejemplos
- &|MODULE 'tools'|\cr
- \Esptab
- &|PROC main()|\cr
- &| IF (toolsbase:=Openlibrary('tools.library',37))=NIL THEN error()|\cr
- &|....|\cr
- &| ToolsFunc()|\cr
- &|....|\cr
- \finsma
- Ahora con |IConvert| convierte |tools.i| a |tools.m|, el cual puedes
- colocar en el directorio |EModules/libraries/|. |IConvert| necesita un
- ensamblador como el A68k de DP para hacer la mayor parte del trabajo de
- traducci\'on del ensamblador.
- \Ejemplos
- &|1> IConvert tools.i|\cr
- mira con |ShowModule| todo lo que se obtuvo del fichero |.i|. Y ya lo podr\'as
- usar en tu programa con:
- \ejemplos
- &|MODULE 'libraries/tools'|\cr
- \Esptab
- &|DEF x:toolsobj, y=TOOLS_CONST|\cr
- \finsma
- La conversi\'on con |IConvert| puede requerir alguna experiencia con
- ensamblador, ya que |IConvert| depende del formato correcto del fichero
- |.i|, justo como los includes de ensamblador de Commodore. Es necesario
- corregir amano cerca del 10\% de los ficheros |.i| para poder {\it convertirlos}.
- Las expresiones que |IConvert| piensa que son correctas son, entre otras:
- \ejemplos
- &\<etiqueta>| EQU |\<expresi\'on\_cualquiera>\cr
- \Esptab
- &|STRUCTURE |\<nombreEs>|,0 ; |si |<>0,| entonces \<estructura>|_SIZEOF|\cr
- &|ULONG |\<nombreEs>|_|\<etiqueta>\cr
- &|BPTR |\<nombreEs>|_|\<etiqueta>\cr
- &| ; |etc.\cr
- &|LABEL |\<nombreEs>|_SIZEOF ; |o |"_SIZE"|\cr
- \Espacio
- Para tener una idea del tipo de expresiones en ensamblador con las que
- puede operar |IConvert|, hecha un vistazo a los includes ensamblador de
- Commodore y comp\'aralos con sus m\'odulos equivalentes (ej.~|intuition.i|).
- \seccion bin/ShowCache, bin/FlushCache.
- El Cach\'e de Modulos de E es un fragmento de memoria que permite
- mantener m\'odulos (|.m|) entre compilaciones. La primera vez que usas un
- cierto m\'odulo, |EC| lo leer\'a del disco y lo pondr\'a en el cach\'e. Las
- siguientes veces |EC| lo encontrar\'a en el cach\'e, y no tendr\'a que leer nada
- de disco. Si |EC| compila un m\'odulo del cual hay una versi\'on anterior en
- el cach\'e lo sacar\'a del cach\'e. Puedes imaginar que esto supone una mejora
- en el tiempo de compilaci\'on enorme cuando se usan gran cantidad de m\'odulos
- y se recompila a menudo, incluso para gente con disco duro,
- \noin Para ver qu\'e es lo que est\'a almacenado en el cach\'e en un momento
- determinado (y cuanta memoria se est\'a empleando |:-)|), teclea:
- \ejemplos
- &|1> ShowCache|\cr
- \finsma
- Una segunda utilidad, |FlushCache|, permite eliminar selectivamente los
- m\'odulos del cach\'e. Las razones de esto pueden ser:
- \item{$-$} No te puedes permitir prescindir de la memoria que utiliza,
- \item{$-$} Creaste un nuevo |.m|, con una herramienta distinta de |EC|, por lo que
- nececitas vaciar el cach\'e a mano.
- \espacio
- El argumento que recibe es la cadena que debe aparacer en el nombre de
- un m\'odulo para eliminarlo del cach\'e. El no dar un argumento implica
- el vaciado completo.
- \ejemplos
- &|1> FlushCache ; vacia todo el cache|\cr
- &|1> FlushCache intuition/ ; elimina modulos de intuition|\cr
- \finsma
- Puedes usar la opci\'on de |EC| |IGNORECACHE/S| para compilar un fuente
- sin usar el cach\'e. Ya est\'e el cach\'e lleno o vac\'{\i}o, |EC| lo leer\'a todo de
- disco, y no pondr\'a nada en \'este.
- \espacio
- Si dos |EC|s intentan acceder al cach\'e simult\'aneamente en multitarea, el
- segundo |EC| actuar\'a como si se le hubiera dado la opci\'on |IGNORECACHE|.
- \seccion rexx/ecompile{.}rexx\nota{?`quien mantiene los otros scripts de ARexx?}.
- Este es un script ARexx para CygnusEd (tm), y te permite compilar
- programas desde el editor. Asigna este script a una tecla de
- funci\'on en el editor con |Install Dos/Arexx Command ...| (comprueba tu
- manual de CED si no estas seguro de como hacer esto). Ahora, escribe tu
- programa, y pulsa |Fx| si quieres compilar. El c\'odigo fuente se guardar\'a
- si es necesario, se invocar\'a al compilador en una ventana consola
- separada, y se ejecutar\'a el programa en una ventana consola diferente.
- Cuando el programa acabe, puedes pulsar \<|return|> para volver al editor
- (el script realiza de forma autom\'atica el cambio de la pantalla de CED
- adelante y detr\'as). Si ocurre un error durante la compilaci\'on, el script
- permitir\'a a CED saltar a la l\'{\i}nea del error despu\'es de pulsar \<|return|>.
- \espacio
- (en el script hay un nombre de camino que indica donde se puede
- encontrar el compilador. Es probable que tengas que cambiarlo. Adem\'as,
- el script copia |EC| a |RAM:| para sistemas con un dispositivo |SYS:| lento,
- puede que quieras deshabilitar esto si tienes un disco duro r\'apido.)
- \seccion bin/o2m.
- Si tienes bloques de fuente en ensamblador grandes que te gustar\'{\i}a
- usar, ser\'{\i}a tedioso tener que, como poco, convertirlos todos a mano a
- ensamblador en l\'{\i}nea de~E\null{}. |o2m| te permite hacer que, de forma sencilla, tu
- macro-ensamblador favorito te lo ensamble todo a un fichero |.o|, y
- entonces |o2m| te convertir\'a ese fichero |.o| a un fichero |.m| para ser
- usado con~E\null{}. Si tienes un fichero |bla.o|:
- \ejemplos
- &|1> o2m bla|\cr
- producir\'a |bla.m|. Sin embargo, el fichero |.o| tendr\'a que seguir ciertas
- reglas. Debe consistir de un s\'olo bloque de c\'odigo con definiciones
- externas (|XDEF|s) para cada s\'{\i}mbolo al que desees hacer referencia desde~E,
- y ning\'un |XREF|\null{}. Por lo general, tu fuente se parecer\'a a:
- \ejemplos
- &| XDEF suma__ii|\cr
- \Esptab
- &|suma__ii:|\cr
- &| move.l 4(a7),d0|\cr
- &| add.l 8(a7),d0|\cr
- &| rts|\cr
- un fragmento de ensamblador que recibe dos argumentos (de
- ah\'{\i} las dos ``|i|'' de entero). Los argumentos se encuentran en la
- pila, donde |4(a7)| es el \'ultimo argumento, |8(a7)| el anterior,~\dots
- \espacio
- |ShowHunk| muestra esto como:
- \ejemplos
- &| hunk_unit:|\cr
- &|HUNK -1 hunk_name:|\cr
- &| hunk_code: 12 bytes|\cr
- &| hunk_ext|\cr
- &| add__ii = $0|\cr
- este tipo de fichero |.o| se puede convertir facilmente a |.m| con |o2m|:
- \ejemplos
- &|/* this module contains 12 bytes of code! */|\cr
- \Esptab
- &|PROC add(a,b)|\cr
- \finsma
- Hay que destacar algunas cosas:
- \item{$-$} si tu c\'odigo ensamblador usa |D3-D7/A4/A5| es probable que debas guardarlos.
- \item{$-$} si una etiqueta no tienen el ``|__|'' con un ``|i|'' para cada funci\'on, se
- convierte en una funci\'on sin par\'ametros. No te preocupes de si la
- etiqueta en realidad hace referencia a datos, puedes obtener la
- direcci\'on de ese |PROC| con |{}|, y usarla como un puntero a tus datos.
- \espacio
- En teor\'{\i}a, |o2m| se podr\'{\i}a usar para enlazar c\'odigo~C a programas en~E,
- sin embargo, a menudo, en la pr\'actica esto no es factible. Si tu
- compilador de~C te permite {\sl ajustar} los ficheros |.o| resultantes un
- poco, podr\'{\i}a funcionar. Aunque nos podemos encontrar con algunos problemas:
- \item{$-$} referencia a funciones de C, por ejemplo |_printf()|.
- \item{$-$} referencia a variables globales creadas por el c\'odigo de inicializaci\'on de~C\null{}.
- El c\'odigo en~C podr\'{\i}a hacer referencia a |DOSBase| como |XREF|, mientras
- que el c\'odigo inicializaci\'on de~E dispone este valor en alg\'un lugar de
- la pila.
- \item{$-$} convenios de llamada/registros.
- \noin Se pueden enlazar con~E funciones de~C que s\'olo realicen
- c\'alculos simples. (Yo he conseguido utilizarlas con \'exito usando
- MaxonC++, cuyo enlazador usa el convenio |__ii| para los par\'ametros.)
- \seccion bin/EYacc.
- Esta es una conversi\'on de la famosa utilidad |Yacc| de Unix, el cual
- ahora produce c\'odigo~E en lugar de c\'odigo~C\null{}. Esta es s\'olo una primera
- versi\'on, por lo que no esperes mucho de ella. Si no tienes idea de lo
- que hace |Yacc|, lee alg\'un texto sobre ello (yo no voy a explicarlo aqu\'{\i}).
- \espacio
- B\'asicamente, puedes escribir ficheros |.y| como siempre, s\'olo que donde
- las acciones sol\'{\i}an escribirse en~C, ahora puedes escribirlas en~E\null{}.
- Mira el ejemplo |Src/Yacc/bcalc.y|.
- \Ejemplos
- &|1> eyacc bcalc.y|\cr
- produce un fichero |yyparse.e|
- \ejemplos
- &|1> ec yyparse|\cr
- genera un m\'odulo, el cual s\'olo contiene la funci\'on |yyparse()|. El resto
- del {\it como mediar con Yacc\/} debe ser an\'alogo al~C.
- \espacio
- ({\it tengo a medias una conversi\'on de Lex a E-Lex, aunque no acabada.}\/)
- \Espacio
- E-Yacc es una modificaci\'on del Yacc 1.8 de Berkeley, de
- |corbett@berkeley.edu|. La inclusi\'on de esta versi\'on modificada en la
- distribuci\'on de~E es totalmente legal, ya que el autor dice en el |README|
- original de BYacc1.8:
- \espacio
- {\sl ``Berkeley Yacc is in the public domain. The data structures and
- algorithms used in Berkeley Yacc are all either taken from documents
- available to the general public or are inventions of the author. Anyone
- may freely distribute source or binary forms of Berkeley Yacc whether
- unchanged or modified. Distributers may charge whatever fees they can
- obtain for Berkeley Yacc. Programs generated by Berkeley Yacc may be
- distributed freely.''}\nota{No veo ning\'un inter\'es en realizar la traducci\'on de esto,
- si no piensas igual, d\'{\i}melo:\hfil\break |u0868551@oboe.etsiig.uniovi.es|\qquad Antonio J. Gomez Glez.}
- \seccion bin/SrcGen.
- {\ninesl (Esta utilidad no ha sido actualizada para funcionar mejor con el
- sistema de m\'odulos de~E, todav\'{\i}a genera el c\'odigo fuente llano (el cual
- se incorpora facilmente en cualquier m\'odulo). S\'olo la actualizar\'e si
- hay mucha demanda ello. Si quieres incluir un GUI decente en tu aplicaci\'on
- echa un vistazo tambi\'en a {\ninett modules/tools/EasyGUI.m}, o a kits m\'as
- recientes como {\ninett BGUI} de Jan van den Baard, autor de GadToolBox.)}
- \espacio
- |SrcGen|, generador de fuente GadToolBox de para E: versi\'on beta
- \espacio
- Necesitar\'as GadToolBox v2.0 o superior, y tener la |gadtoolsbox.library|
- que viene con \'el en tu |LIBS:|. Ahora, crea con GTB alg\'un ejemplo simple
- (una ventana con unos pocos gadgets\b/menus etc.), gr\'abalo como |bla| (el
- nombre del fichero ser\'a |bla.gui|), y teclea:
- \ejemplos
- &|1> SrcGen bla|\cr
- &|1> EC bla|\cr
- &|1> bla|\cr
- \finsma
- |bla.e| tendr\'a las rutinas de apertura de tu interface, as\'{\i} como algunas
- rutinas para manejar mensajes IDCMP, errores,~\dots, y un |main()| sencillo
- que s\'olamente espera por una selecci\'on. Ah\'{\i} puedes poner tu propio
- c\'odigo. Mira el patr\'on de la l\'{\i}nea de comandos para ver como se evita
- que |SrcGen| genere esas rutinas.
- \espacio
- Eso es para todo lo que sirve. Si tienes problemas, simplemente
- comprueba el c\'odigo que se gener\'o.
- \seccion bin/EBuild.
- |EBuild| es una copia de |Make|, y funciona de forma similar. |EBuild| es
- una utilidad que te ayuda a recompilar las partes necesarias de una
- aplicaci\'on grande despu\'es de modificarla. Escribes un fichero |.build|
- en el directorio que contiene los fuentes de tu proyecto. El fichero
- contiene informaci\'on sobre qu\'e fuentes dependen de qu\'e otros, y qu\'e
- acciones se deben llevar a cabo si es necesario reconstruir un m\'odulo o
- un ejecutable. |EBuild| comprueba las fechas de los ficheros para ver si
- se ha modificado un fuente despu\'es de la \'utima compilaci\'on, y si el
- fuente usa m\'odulos que tambi\'en han sido modificados, compilando esos
- \'ultimos primero.
- \espacio
- La sintaxis es como la del make de Unix. En resumen, ``|#|'' precede
- l\'{\i}neas con comentarios, y en:
- \ejemplos
- & |objetivo: dep1 dep2 ...|\cr
- & | accion1|\cr
- & | accion2|\cr
- & | ...|\cr
- |objetivo| es el fichero resultado del que estamos hablando, en la mayor\'{\i}a
- de los casos un ejecutable o un m\'odulo, aunque puede ser cualquier cosa.
- Tras los ``|:|'' puedes escribir todos los ficheros de los que depende,
- probablemente su fuente, y otros m\'odulos. Las acciones de las l\'{\i}neas que
- le siguen son comandos de AmigaDos normales, y es necesario precederlos
- de al menos un espacio o un tabulador para distinguirlas de objetivos.
- \Ejemplos
- & |bla: bla.e defs.m|\cr
- & | ec bla quiet|\cr
- este sencillo ejemplo recompilar\'a |bla.e| si ha sido modificado, o si
- |defs.m| ha cambiado.
- \espacio
- Si tecleas |EBuild| sin argumentos, |EBuild| se asegurar\'a de que el
- primer objetivo est\'e actualizado. Por otra parte, puedes darle las siguientes
- opciones:
- \ejemplos
- &|TARGET,FROM/K,FORCE/S:|\cr
- \finsma
- Si das un |TARGET|\nota{objetivo}, |EBuild| empezar\'a con otro objetivo. |FROM|
- te permite usar otro fichero que no sea |.build|, y |FORCE| reconstruir\'a
- todo, independientemente de si era necesario o no. Veamos un ejemplo:
- \ejemplos
- &|# fichero build de prueba|\cr
- \Esptab
- &|all: bla burp|\cr
- &|defs.m: defs.e|\cr
- &| ec defs quiet|\cr
- &|bla: bla.e defs.m|\cr
- &| ec bla quiet|\cr
- &|burp: burp.e|\cr
- &| ec burp quiet|\cr
- &|limpia:|\cr
- &| delete defs.m bla burp|\cr
- este fichero build es sobre dos programas, |bla| y |burp|, de los cuales |bla|
- tambi\'en depende de un m\'odulo |defs.m|. Incorpora un objetivo extra no real
- |limpia| de forma que puedas escribir |EBuild limpia| para borrar todos
- los ficheros generados.
- \espacio
- Se pueden a\~nadir otras dependencias y acciones con facilidad. Por
- ejemplo, si tu proyecto usa un analizador generado por E-Yacc:
- \begintt
- yyparse.m: parser.y
- eyacc parser.y
- ec yyparse quiet
- \endtt
- \espacio
- O si incorpora c\'odigo de macro-ensamblador como m\'odulo de herramienta
- usado a menudo:
- \begintt
- blerk.m: blerk.s
- a68k blerk.s
- o2m blerk
- copy blerk.m emodules:tools
- flushcache tools/blerk
- \endtt
- \espacio
- En el momento en el que logres conocer |EBuild|, descubrir\'as que lo
- puedes usar para m\'as prop\'ositos a parte de \'este. M\'{\i}ralo como una
- herramienta de scripts inteligente.
- \espacio
- Si quieres descubrir en detalle de lo que puede hacer |EBuild|, lee la
- documentaci\'on de alg\'un make de Unix, ya que |EBuild| es, de alguna forma,
- compatible con \'el. Lo que de momento no hace es:
- \item{$-$} eliminar dependencias c\'{\i}clicas.
- \item{$-$} permitir ``|\|'' al final de una l\'{\i}nea para reglas m\'as largas.
- \item{$-$} definiciones constantes.
- \espacio
- Jason Hulance ha actualizado |EBuild| para la versi\'on v3.1 del
- compilador de~E, para corregir el error que ejecutaba acciones en
- orden inverso. Tambi\'en cambi\'o la ejecuci\'on de la acci\'on a un script
- (transparente). En ese script a la variable |target| se le da el valor
- del objetivo actual. Por ejemplo:
- \begintt
- test: test.e
- ec "$target"
- if warn
- echo "Error: fallo la compilacion"
- else
- echo "Compilado OK... ejecutando"
- "$target"
- endif
- \endtt
- que equivale al siguiente c\'odigo del |EBuild| antiguo, aunque permite m\'as cosas.
- \begintt
- all: test
- echo "ok, ejecutando:"
- test
- test: test.e
- ec -q test
- \endtt
- \seccion EE / Aprof.
- ({\ninesl Estos se describen en su propia documentaci\'on en el directorio {\ninett tools}.}\/)
- \seccion EDBG.
- |EDBG| es el depurador e nivel de fuente de~E\null{}. Para usarlo
- compila\nota{{\bf No} distribuyas un programa en el que alguna parte ha sido compilada
- con |DEBUG/S| (puedes comprobarlo con |ShowHunk|, no debe contener ning\'un
- |hunk_debug|). Los programas con informaci\'on de depuraci\'on se compilan con
- |NOP|s extra para facilitar la depuraci\'on, lo cual no es deseable en el
- c\'odigo final.} tu fuente con la opci\'on |DEBUG| (esto funciona tanto para el
- programa principal como para los m\'odulos), lo cual a\~nadir\'a informaci\'on de
- depuraci\'on en tu ejecutable\b/m\'odulo.
- \espacio
- Aseg\'urate siempre de que tanto el c\'odigo fuente como el compilado
- est\'an en el directorio actual, entonces lanza |EDBG| con:
- \ejemplos
- &|1> EDBG nombreejecutable|\cr
- \Ejemplos
- patr\'on:&|EXECUTABLE/A,PUBSCREEN/K:|\cr
- con |PUBSCREEN| puedes hacer que |EDBG| corra en cualquier lugar
- (|PUBSCREEN=Workbench| para que funcione en el Workbench). Por omisi\'on |EDBG|
- abre su propia pantalla, la cual es una copia del Workbench en tama\~no y
- modo de pantalla. |EDBG| funciona bien en la tarjeta gr\'afica Picasso,~\dots
- \noin |EDBG| abre una ventana para cada fuente en tu proyecto, y empezar\'a con
- el que contiene a |main()|. Desde la que puedes recorrer tu c\'odigo, y se
- abrir\'an ventanas autom\'aticamente cuando sean necesarias. Cuando el c\'odigo
- no tiene un fuente adjunto, s\'olo se puede ejecutar (lo cual es \'util a
- veces, si no es necesario depurarlo).
- \noin Desde ese momento todo es bastante intuitivo. Los botones m\'as
- importantes son las dos primeras im\'agenes, que son el de {\sl recorre sobre/en}
- ({\sl step over/in}\/). Recorre en sigue el c\'odigo paso a paso seg\'un se ejecuta,
- recorre sobre hace lo mismo pero no entra en las subrutinas.
- (!`Pru\'ebalo!, el depurador es bastante intuitivo).
- \noin Otras funciones sacan ventanas de memoria o registros, y algunas otras
- funciones (algunas sin implementar). Una importante es hacer un doble
- click en nombres de variables: \'esto nos mostrar\'a su contenido en la
- ventana temporal (ya lo s\'e, esto ser\'a algo m\'as c\'omodo en el futuro).
- \noin Pegas:
- \item{$-$} El programa que se depura corre en la misma tarea que |EDBG|\null{}. Esto quiere
- decir que todo c\'odigo que haga cosas especiales en la tarea deber\'a ser
- cuidadoso. Un ejemplo es |Forbid()|.
- \item{$-$} Un caso especial es |ReadArgs()|. Dado que |EDBG| ya ley\'o los argumentos,
- una llamada del programa que se depura causar\'a una lectura de la
- consola. De forma que puedes teclear convenientemente los argumentos de
- tu programa en la l\'{\i}nea de comandos y pulsar \<|return|>.
- \Espacio
- |EDBG| todav\'{\i}a es algo beta, aunque ya bastante \'util. Le faltan gran
- cantidad de funciones, y tendr\'as que esperar algo antes de que se lleguen
- a implementar. (por lo tanto, no vengas a contarme que ``{\sl X no
- funciona}'' o que ``{\sl |EDBG| necesita X}'' porque {\bf ya lo se}.)
- \Espacio
- \subsec Las opciones |LINEDEBUG| y |SYM|.
- La opci\'on |LINEDEBUG| a\~nade informaci\'on |linedebug| a tu ejecutable
- (para cada l\'{\i}nea de c\'odigo dentro de un |PROC|)\null. |EDBG| necesita esta opci\'on,
- aunque la opci\'on |DEBUG| la activa de forma autom\'atica. |LINEDEBUG| es
- parcialmente compatible con el |HUNK_DEBUG| |"LINE"| producido por otros
- compiladores\b/ensambladores, por lo que tambi\'en puede ser \'util con otras
- herramientas de depuraci\'on. La opci\'on |SYM| no es necesaria para |EDBG|,
- pero puede ser \'util para otros, como |AProf| o desensambladores.
- \Espacio
- \subsec Errores m\'as graves conocidos.
- \item{$-$} no puedes desplazar la l\'{\i}nea actual fuera de la parte visible en una
- ventana de fuente porque |EDBG| intenta mantenerla a la vista.
- \item{$-$} muchos otros~\dots, probablemente
- \seccion PreProcesador de |EC|.
- |EC| tiene un preprocesador interno que ofrece substituciones de macros
- y compilaci\'on condicional. Estas no son caracter\'{\i}sticas del lenguaje~E,
- sino que se han integrado en |EC| por velocidad y flexibilidad.
- \subsec Activando el preprocesador.
- Hasta que no escribas:
- \ejemplos
- &|OPT PREPROCESS|\cr
- |EC| se comportar\'a como siempre. Esta |OPT| es necesaria para cualquier
- caracter\'{\i}stica relacionada con el preprocesador.
- \subsec Macros.
- El macropreprocesador es compatible con |Mac2E| y el prepocesador del~C\null{}. Puedes
- definir macros con:
- \begintt
- #define NOMBREMACRO
- #define NOMBREMACRO CUERPO
- #define NOMBREMACRO(ARG, ...) CUERPO
- #define NOMBREMACRO(ARG, ...) CUERPO \
- RESTO DEL CUERPO
- \endtt
- |NOMBREMACRO| y |ARG| pueden tener tanto may\'usculas como min\'usculas, y pueden
- contener |_| y |0-9| como siempre. Se pueden a\~nadir espacios en cualquier
- lugar menos entre |NOMBREMACRO| y |(|, ya que sino |EC| no podr\'{\i}a distinguir
- entre argumentos y el cuerpo.
- \noin El |CUERPO| puede contener cada uno de los argumentos tantas veces como
- quiera. Una macro puede continuar en la l\'{\i}nea siguiente si se precede el
- {\sl final-de-l\'{\i}nea}\/ con un |\|. Una macro sin cuerpo puede ser \'util en
- combinaci\'on con compilaci\'on condicional.
- \espacio
- Los identificadores de macro tienen precedencia sobre los dem\'as.
- Las macros definidas en un m\'odulo s\'olo se guardan en el m\'odulo si se
- activa |OPT EXPORT| (|#define| no se puede preceder con |EXPORT|). Si eso
- representa un problema, mant\'en las macros juntas en su propio m\'odulo.
- Las macros de los m\'odulos se pueden usar en c\'odigo diferente simplemente
- con importarlas con |MODULE|, y usando |OPT PREPROCESS|.
- \subsec Usando una macro.
- El uso de |NOMBREMACRO| en cualquier punto del programa har\'a que se
- inserte el |CUERPO| de la macro en ese punto. Ten en cuenta que \'esta es una
- substituci\'on de texto, y tiene poco que ver con la sintaxis de~E en s\'{\i}.
- Si las macros tienen argumentos, \'estos se insertar\'an en sus respectivos
- lugares del cuerpo de la macro. Si el cuerpo (o los argumentos) contienen
- m\'as macros, \'estos se expander\'an m\'as tarde.
- \noin Ejemplo:
- \begintt
- #define MAX(x,y) (IF x>y THEN x ELSE y)
- WriteF('el mayor = \d\n',MAX(10,a))
- \endtt
- es lo mismo que escribir:
- \begintt
- WriteF('el mayor = \d\n',(IF 10>a THEN 10 ELSE a))
- \endtt
- \espacio
- Esto nos muestra el peligro de las macros: escribir
- |MAX(computacion_grande(),1)| generar\'a c\'odigo que ejecuta
- |computacion_grande()| dos veces, ya que
- simplemente se copia textualmente. Ten cuidado con eso.
- \subsec Compilaci\'on condicional.
- Esto puede ser \'util si quieres decidir en el momento de la compilaci\'on
- qu\'e parte de tu c\'odigo quieres usar. Veamos primero un ejemplo:
- \begintt
- #define DEPURA
- ->#define DEPURABIEN
- #ifdef DEPURA
- WriteF('entrando en bla() con x = \d\n',x)
- #ifdef DEPURABIEN
- WriteF('volcando memoria...\n')
- /* ... */
- #endif
- #endif
- \endtt
- \Espacio
- Su sintaxis es:
- \ejemplos
- & |#ifdef NOMBREMACRO|\cr
- \ejemplos
- & |#ifndef NOMBREMACRO|\cr
- el fragmento de c\'odigo que lo sigue se, o no se compilar\'a dependiendo de
- si |NOMBREMACRO| fu\'e definido. Puedes hacer esto simplemente con:
- \ejemplos
- & |#define MIBANDERA|\cr
- o algo parecido. Finaliza el bloque compilado condicionalmente con:
- \ejemplos
- & |#endif|\cr
- adem\'as, este tipo de bloques se puede anidar como se vi
- en el ejemplo.
- \endchapter\saltacap
- \beginchapter Ap\'endice A. Correspondencia\\con otros\\lenguajes
- \ninepoint
- En este ap\'endice veremos una serie de tablas que tratan de mostrar la equivalencia
- de diferentes elementos de E con otros lenguajes.
- En las dos primeras columnas aparecer\'an las equivalencias entre E y
- AnsiC/C++, la tercera columna est\'a reservada para un tercer lenguaje.
- La mayor parte de las veces usar\'e Pascal en esa columna, aunque si una caracter\'{\i}stica
- lo pide, usar\'e otros (LISP, por ejemplo, con expresiones entrecomilladas,
- Ada con excepciones, etc~\dots)
- \noin No te tomes muy en serio estas tablas, ya que cada lenguaje tiene sus peculiaridades.
- \medskip
- \halign to\hsize{\tt#\hfil\tabskip=2em plus30em minus1em& #\hfil& \tt#\hfil\tabskip=0pt\cr
- \bartab
- \multispan3\sc ESTRUCTURA/SENTENCIAS\hfil\cr
- \sc E& \sc C/C++ & \sc Pascal \cr
- \bartab
- PROC x() & |int x() {| & FUNCTION x: INTEGER; \cr
- PROC x(y,z) & |int x(y,z) {| & FUNCTION x(y,z:INTEGER):INTEGER; \cr
- PROC x(y=1) & |int x(y=1) {| & \rm -- \cr
- ENDPROC & |return 0; };| & x:=0; END; \cr
- ENDPROC e & |return e; };| & x:=e; END; \cr
- ENDPROC e,f,g & -- & \rm -- \cr
- RETURN e & |return e;| & \rm ? \cr
- \Esptab
- IF e & |if(e) {| & IF e THEN BEGIN \cr
- ELSEIF e & |} else if(e) {| & END ELSE IF e THEN BEGIN \cr
- ELSE & |} else {| & END ELSE BEGIN \cr
- ENDIF & |};| & END; \cr
- IF e THEN s & |if(e) s;| & IF e THEN s; \cr
- IF e THEN s ELSE t & |if(e) s else t;| & IF e THEN s ELSE t; \cr
- \Esptab
- FOR x:=e TO f & --$^{(1)}$ & FOR x:=e TO f DO BEGIN \cr
- FOR x:=e TO f STEP i & -- & \rm --$^{(2)}$ \cr
- EXIT e & |if(e) break;| & \rm -- \cr
- ENDFOR & -- & END; \cr
- FOR x:=e TO f DO s & -- & FOR x:=e TO f DO s; \cr
- \Esptab
- WHILE e & |while(e) {| & WHILE e DO BEGIN \cr
- EXIT e & |if(e) break;| & \rm -- \cr
- ENDWHILE & |};| & END; \cr
- WHILE e DO s & |while(e) s;| & WHILE e DO s; \cr
- s; WHILE e & |for(s;e;u) {| & s; WHILE e DO BEGIN \cr
- \quad t; u & | t;| & \quad t; u \cr
- ENDWHILE & |};| & END; \cr
- \Esptab
- REPEAT & |do {| & REPEAT \cr
- UNTIL e & |} while(!e);| & UNTIL e; \cr
- \Esptab
- LOOP & |for(;;) {| & WHILE TRUE DO BEGIN\rm (?) \cr
- ENDLOOP & |};| & END; \cr
- \Esptab
- SELECT x & |switch(x) {| & CASE x OF \cr
- SELECT x OF y & |switch(x) {| & CASE x OF \cr
- CASE 1; s... & |case 1: s...; break| & 1: BEGIN s... END \cr
- CASE a+1 & -- & \rm -- \cr
- CASE 1,2,3 & |case 1: case 2: case3:| & 1,2,3: \cr
- CASE "a".."z" & -- & \rm -- \cr
- ENDSELECT & |};| & END \cr
- \Esptab
- INC x & |x++;| & x:=x+1; (INC()) \cr
- DEC x & |x--;| & x:=x-1; (DEC()) \cr
- JUMP lab & |goto lab;| & GOTO lab; \cr
- x:=e & |x=e;| & x:=e; \cr
- /* */ & |/* */| & |{ }| \cr
- -> & |//| & \rm -- \cr
- \bartab
- \multispan3$^{(1)}$ mira |WHILE|; C no tiene |FOR|, |for| es otra forma de escribir |while|\hfil\cr
- \multispan3$^{(2)}$ s\'olo |STEP -1| con |DOWNTO|\hfil\cr
- \bigskip
- \halign to\hsize{\tt#\hfil\tabskip=2em plus30em minus1em& #\hfil& \tt#\hfil\tabskip=0pt\cr
- \bartab
- \multispan3\sc VALORES\hfil\cr
- \sc E& \sc C/C++& \sc Pascal\cr
- \bartab
- 1 & |1| & 1 \cr
- 1.0 & |1.0| & 1.0 \cr
- \$1 & |0x1| & \rm ? \cr
- \%1 & ? & \rm ? \cr
- "a" & |'a'| & chr(97) (?) \cr
- 'blabla' & |"blabla"|& 'blabla' \cr
- [1,2,3] & --$^{(1)}$ & \rm -- \cr
- [1,2,3]:INT & -- & \rm -- \cr
- \bartab
- \multispan3$^{(1)}$ |mifunc([1,2,3]) --> int temp[]={1,2,3}; mifunc(temp);|\hfil\cr
- \medskip
- \halign to\hsize{\tt#\hfil\tabskip=2em plus30em minus1em& #\hfil& \tt#\hfil\tabskip=0pt\cr
- \bartab
- \multispan3\sc OPERADORES\hfil\cr
- \sc E& \sc C/C++& \sc Pascal\cr
- \bartab
- + - * / & |+ - * /| & + - * DIV \cr
- = <> > < >= <= & |== != > < >= <=| & = <> > < >= <= \cr
- AND OR (log) & |&& |\|\| & and or \cr
- AND OR (bit) & |& |\| & \rm ? \cr
- SIZEOF x & |sizeof(x)| & \rm -- \cr
- `e & --& --$^{ (1)}$ \cr
- \^{}x $^{ (4)}$ & |*x| & ... \cr
- $\{$x$\}$ & |&x| & ... \cr
- x++ & |x++| & \rm -- \cr
- x-- & |--x| & \rm -- \cr
- -x & |-x| & -x \cr
- IF e THEN f ELSE g & |e ? f : g| & \rm -- \cr
- x.y & |x->y| & x\^{}.y \cr
- \rm -- & |x.y| & x.y \cr
- x.y.z & |x->y->z| & x\^{}.y\^{}.z \cr
- x:=e & |x=e| & \rm -- \cr
- e BUT f & |(e,f)| & \rm -- \cr
- x[] & |x[0] *x|$^{(2)}$ & x[0] \cr
- x[1] & |x[1]| & x[1] \cr
- x[1] $^{(3)}$ & |&x[1]| & \rm ? \cr
- x[1].y & |x[1]->y| & x[1]\^{}.y \cr
- x[]++ & |*x++| & \rm -- \cr
- x[1].y++ & |*(x+1)++| & \rm -- \cr
- x::y.a & |((y *)x)->a| & \rm -- \cr
- x.y::z.a & |((z *)x->y)->a| & \rm -- \cr
- \bartab
- \multispan3$^{(1)}$ mira expresiones entrecomilladas.\hfil\cr
- \multispan3$^{(2)}$ otros tambi\'en mantienen la equivalencia entre |*(x+e)| y |x[e]|.\hfil\cr
- \multispan3$^{(3)}$ con |ARRAY OF |\<objeto>\hfil\cr
- \multispan3$^{(4)}$ {\bf s\'olo} para pasar por referencia. En otro caso: |[]|\hfil\cr
- \medskip
- \halign to\hsize{\tt#\hfil\tabskip=2em plus30em minus1em& #\hfil\tabskip=0pt\cr
- \bartab
- \multispan2\sc PROGRAMACION ORIENTADA A OBJETOS\hfil\cr
- \sc E& \sc C/C++\cr
- \bartab
- OBJECT x & |class x {| \cr
- OBJECT x OF y & |class x : y {| \cr
- self.i & |this->i| \cr
- PROC a OF x IS self.i & |virtual int x::a() { return i; }| \cr
- \rm -- & |int x::a() { return i; }| \cr
- PROC a OF x IS EMPTY & |virtual int x::a() =0| \cr
- PUBLIC & |public:| \cr
- a.method$^{(1)}$ & |a->method|$^{(1)}$ \cr
- \bartab
- \multispan2$^{(1)}$ mira tambi\'en en el siguiente apartado en NEW\hfil\cr
- \medskip
- \halign to\hsize{\tt#\hfil\tabskip=2em plus30em minus1em& #\hfil& \tt#\hfil\tabskip=0pt\cr
- \bartab
- \multispan3\sc CONSTANTES/TIPOS\hfil\cr
- \sc E& \sc C/C++& \sc Pascal\cr
- \bartab
- CONST X=1 & |#define X 1| & CONST X=1; \cr
- & |const int X=1;| \cr
- ENUM X,Y,Z & |#define X 0 (etc.)| & TYPE x=(X,Y,Z); \cr
- & |enum x{X,Y,Z};| \cr
- SET X,Y,Z & -- & TYPE x=SET OF (X,Y,Z); \cr
- DEF & & VAR \cr
- x & |int x; (or: long x;)| & x:INTEGER; \cr
- x:LONG & |int x;| & x:INTEGER; \cr
- x:PTR TO y & |struct y* x;| & x:\^{}y; \cr
- x:y & |struct y x;| & x:y; \cr
- x[10]:ARRAY OF y & |struct y x[10];| & x:ARRAY [0..9] OF y; \cr
- x[10]:STRING & --$^{(1)}$ & x:STRING[10];$^{(2)}$ \cr
- x[10]:LIST & --$^{(1)}$ & \rm --$^{(1)}$ \cr
- x:REG & |register int x;| \cr
- OBJECT x & |struct x {|$^{(3)}$ & TYPE x = RECORD \cr
- \qquad y:CHAR,z:INT & | char y; short z;| & \qquad y:CHAR; z:INTEGER; \cr
- ENDOBJECT & |};| & END; \cr
- \bartab
- \multispan3$^{(1)}$ en C sim\'ulalo con un arreglo de char/int con comprobaci\'on de rango propia.\hfil\cr
- \multispan3$^{(2)}$ no en Wirth Pascal, pero disponible en todos los dialectos populares.\hfil\cr
- \multispan3$^{(3)}$ o clase p\'ublica.\hfil\cr
- \medskip
- \halign to\hsize{\tt#\hfil\tabskip=2em plus30em minus1em& #\hfil& \tt#\hfil\tabskip=0pt\cr
- \bartab
- \multispan3\sc FUNCIONES PREDIFINIDAS Y RESERVA DE MEMORIA\hfil\cr
- \multispan3\sl (s\'olo algunas funciones como ejemplo.)\hfil\cr
- \sc E& \sc C/C++& \sc Pascal\cr
- \bartab
- WriteF(fs,...) & |printf(fs,...);| & WriteLn(a,b,...); \cr
- & |cout << a << b ... ;| \cr
- ReadStr(f,s) & |scanf(fs,...)| & ReadLn(s) \cr
- Val(s) & & Val() \cr
- & |cin >> s;| \cr
- StrCopy(s,s,n)$^{(1)}$ & |strcpy(s,s)| & s:=s;$^{(2)}$ \cr
- \Esptab
- Mod(e,e) & |e%e| & e MOD e \cr
- Shl(e,n) & |e<<n| & Shl() \cr
- Long(e) & -- & \rm -- \cr
- \Esptab
- p:=New(e) & |p=malloc(e);| & New(p); \cr
- NEW p & |p=new type;| \cr
- NEW p.constr() & |p=new constr()| & \rm -- \cr
- NEW [e,f,g] & -- & \rm -- \cr
- Dispose(p) & |free(p);| & Dispose(p); \cr
- END p & |delete p;| \cr
- \bartab
- \multispan3$^{(1)}$ aseg\'urate de convertir los arreglos de char en |STRING|s de verdad. \hfil\cr
- \multispan3$^{(2)}$ no se que funci\'on se necesita en el caso de punteros.\hfil\cr
- \medskip
- \halign to\hsize{\tt#\hfil\tabskip=2em plus30em minus1em& #\hfil& \tt#\hfil\tabskip=0pt\cr
- \bartab
- \multispan3\sc UNIFICCION Y CELDAS LISP\hfil\cr
- \sc E& \sc LISP& \sc PROLOG\cr
- \bartab
- <1\|2> & |(1 . 2)| & [1\|2] \cr
- <1,2,3> & |(1 2 3)| & [1,2,3] \cr
- <1,2\|3> & |(1 2 . 3)| & [1,2\|3] \cr
- \esptab
- \sc E& \sc HASKELL& \sc PROLOG\cr
- \bartab
- e <=> <x\|y> & |(x:y) = e| & e = [X\|Y] \cr
- e <=> <1,2,x> & |[1,2,x] = e| & e = [1,2,X] \cr
- e <=> [1,x] & -- & \rm -- \cr
- \bartab
- \bigskip
- \halign to\hsize{\tt#\hfil\tabskip=2em plus30em minus1em& #\hfil& \tt#\hfil\tabskip=0pt\cr
- \bartab
- \multispan3\sc EXPRESIONES ENTRECOMILLADAS\hfil\cr
- \esptab
- \sc E& \sc LISP& \sc MIRANDA\cr
- \bartab
- `e & |(QUOTE e) 'e| & $^{(3)}$ \cr
- & |(LAMBDA () e)| & $^{(1)}$ \cr
- `x+y & |'(+ x y)| \cr
- Eval(`e) & |(EVAL `e)| \cr
- ForAll(v,l,`e) & --$^{(2)}$ \cr
- MapList(v,l,l,`e) & |(MAPCAR (LAMBDA (V) E) L)| & map ($\backslash$v->e) l \cr
- \bartab
- \multispan3$^{(1)}$ realmente |QUOTE|, pero usado a veces donde en |LISP| se usar\'{\i}a |LAMBDA|,
- como en |MapList|()\hfil\cr
- \multispan3$^{(2)}$ ni siquiera en ProLog, mira en otros lenguajes de l\'ogica.\hfil\cr
- \multispan3$^{(3)}$ en su lugar se usar\'{\i}a 'lazyness'\hfil\cr
- \espacio
- Ejemplo:
- \Ejemplos
- \qquad E: & |MapList({x},[1,2,3,4],a,`x*x)| \cr
- \qquad MIRANDA: & |map (\x->x*x) [1,2,3,4]| \cr
- \qquad LISP: & |(MAPCAR (LAMBDA (X) (* X X) `(1 2 3 4))| \cr
- \bigskip
- \halign to\hsize{\tt#\hfil\tabskip=2em plus30em minus1em& #\hfil& \tt#\hfil\tabskip=0pt\cr
- \bartab
- \multispan3\sc EXCEPCIONES\hfil\cr
- \esptab
- \sc E& \sc C/C++& \sc ADA\cr
- \bartab
- PROC x() HANDLE & |int x() { try {| & function x is begin \cr
- EXCEPT & |} catch (exc) {|$^{(1)}$& exception \cr
- EXCEPT DO & -- & \rm -- \cr
- ENDPROC & |}};| & end x; \cr
- \Esptab
- Raise(e) & |throw e;| & raise e; \cr
- Throw(e,f) & ? & \rm -- \cr
- ReThrow() & |throw e;| & raise e; \cr
- RAISE "MEM" IF New()=0 & -- & \rm --$^{(2)}$ \cr
- \bartab
- \multispan3$^{(1)}$ |catch| s\'olo controla un excepci\'on concreta, es bastante diferente de como se usan los\hfil\cr
- \multispan3 \quad manejadores de excepciones generales en E. \hfil\cr
- \multispan3$^{(2)}$ el sistema en tiempo de ejecuci\'on lanza algunas excepciones, pero no estoy seguro de\hfil\cr
- \multispan3 \quad si se pueden {\it definir} excepciones lanzadas autom\'aticamente en ADA. \hfil\cr
- \bigskip
- \noin En las tablas aparec\'{\i}an una serie de abreviaturas y signos cuyo significado es
- el siguiente:
- \Ejemplos
- \qquad --& = caracter\'{\i}stica no disponible en el lenguaje en cuesti\'on.\cr
- \qquad ?& = el autor no tiene idea a qu\'e se traduce esa caracter\'{\i}stica. (o no est\'a seguro).\cr
- \qquad ...& = puede estar disponible, pero no en relaci\'on 1:1 que la haga interesante.\cr
- \qquad x,y,z& = indetificadores arbritarios.\cr
- \qquad e,f,g& = expresiones arbritarias.\cr
- \qquad s,t,u& = sentencias arbritarias.\cr
- \qquad i,j,k& = enteros arbritarios.\cr
- \qquad etc.\cr
- \endchapter\saltacap
- \beginchapter Ap\'endice B. FAQ
- \ninepoint
- Esta lista-FAQ (Frequently Asked Questions\nota{Preguntas realizadas
- con Frecuencia, de fecha 1-10-04 al 1-12-94}) ha sido recogida mirando en el
- email viejo y escongiendo aquellas preguntas que se repet\'{\i}an una y otra vez.
- \medskip
- \parindent=0pt
- \advance\leftskip by15pt
- \advance\rightskip by15pt
- {\bf Compilador/Enlazador/Ejecutables}
- \pregunta{?`C\'omo puedo enlazar c\'odigo~E con otros lenguajes\b/usar un formato de
- objeto estandard?}
- La conversi\'on entre |.m| y |.o| no es en realidad un gran problema, como
- podemos ver con la utilidad |o2m|, que permite la cooperaci\'on entre~E y
- macro-ensambladores bastante bien. El problema con el~C radica en el
- c\'odigo compilado, no el formato del fichero. A no ser C~trivial,
- cualquier c\'odigo compilado en~C har\'a referencia a cosas como |_DOSBase|,
- librer\'{\i}as de enlace, bases de pila, y otras cosas del c\'odigo de
- inicializaci\'on que~E proporciona de una forma algo diferente, por
- ejemplo, el c\'odigo de inicializaci\'on de E es bastante diferente de el
- de los compiladores de~C\null{}. Estos problemas pueden aparecer incluso entre
- dos compiladores de~C\null{}. Si puedes conseguir que tu compilador de~C
- genere un |.o| sin referencias externas, etc, entonces podr\'as enlazarlo
- con~E (yo ya lo he hecho una vez con MaxonC++).
- \pregunta{?`Puedo enlazar con \/|amiga.lib|?}
- De momento no. Aunque en menor medida, esto tiene los mismos problemas
- que los ficheros |.o|, aunque con la ayuda de un ensamblador y |o2m| se
- podr\'{\i}a traducir un fichero |.lib| a |.m|, de hecho, ya se ha realizado para
- algunas. S\'olo es cuesti\'on de tiempo que alguien lo haga para (partes
- de) |amiga.lib|.
- \pregunta{?`Se puede hacer residente el c\'odigo de~E?}
- Practicamente {\bf todo} el c\'odigo de E ya se puede hacer residente sin la
- ayuda del programador. Seg\'un creo, la \'unica construcci\'on~E que puede
- violar \'esto es un lista est\'atica |[]| con una expresi\'on en ella (como |[a]|
- por ejemplo. Con |[1]| y |NEW [a]| van bien).
- \pregunta{Tengo una aplicaci\'on con ensamblador en l\'{\i}nea, y con |OPTI/S|
- no funciona bien. ?`Qu\'e sucede?}
- El ensamblador en l\'{\i}nea puede usar los mismos registros a la vez que el
- opimizador de registros. Busca en otra parte del documento sobre eso.
- \pregunta{He escrito \/|X| tanto en~C como en~E, y la versi\'on en~E es
- \/|Y|~veces m\'as r\'apida\b/lenta. ?`A~qu\'e se debe?}
- No es f\'acil hacer una comparaci\'on de forma totalmente objetiva. A
- menudo, se puede dar el caso que alguno de los dos tenga rutinas m\'as
- optimizadas para algo (manejo de cadenas, E/S, etc~\dots). El uso de un
- profiler puede ayudar a descubrirlo. Si el c\'odigo en cuesti\'on s\'olo
- realiza c\'alculos, no hay ninguna raz\'on por la que alguno de los dos sea
- significativamente m\'as lento que el otro, si se usan correctamente.
- \pregunta{He escrito un buen \/|misutils.m|, y aunque s\'olo use una funci\'on
- suya, \/|EC|~lo enlaza todo. !`No me gusta!.}
- El estilo de escritura de m\'odulos en E es mantenerlos como unidades
- relativamente peque\~nas, s\'olo con c\'odigo y datos relacionados. (Esto
- tiene m\'as sentido si sabes que el m\'odulo es la unidad de ocultamiento
- de datos de~E\null{}). !`Div\'{\i}delo!
- \pregunta{?`Puedo dejar |EC| residente?}
- No, de momento no. El propio |EC| esta escrito en un estilo de
- ensamblador anticuado, y no se puede hacer residente |;-)|
- \Espacio
- {\bf Recursos}
- \pregunta{En la documentaci\'on no se explican las funciones de
- |intuition.library|,~\dots\quad ?`Por qu\'e?}
- Esas funciones no son parte de E, sino que forman parte del SO de Amiga.
- Como tales, se describen en los documentos de Commodore, no en los
- documentos de E\null{}. ``{\sl The AMIGA ROM Kernel Reference Manuals\/}'' son una serie
- de libros publicados por Addison Wesley. Un buen lugar por donde
- empezar es el libro de ``{\sl Libraries\/}'' de esa serie, ISBN~0-201-56774-1.
- Tambi\'en hay otros libros que merecen la pena ser considerados, como el
- ``{\sl The Amiga Guru Book\/}'' de Ralph Babel.
- \pregunta{Me gustar\'{\i}a leer m\'as c\'odigo fuente a parte del que viene con la
- distribuci\'on, ?`Donde debo buscar?}
- Hay cantidad de lugares en los que mirar, aunque el mejor sin duda
- alguna es {\it Aminet} (Una colecci\'on de sites de FTP en Internet), por
- ejemplo |ftp.luth.se|. En el directorio |/pub/aminet/dev/e| encontrar\'as
- todo tipo de cosas relacionadas con~E\null{}. Algunas BBSs fuera de Internet
- tambi\'en tienen {\it Aminet}, e incluso hay disponibles CDROMS\null{}. Otro buen
- lugar para recoger fuentes y hablar con buenos programadores en~E, es
- la lista de correo de~E\null{}. Env\'{\i}a un email con ``|HELP|'' en el cuerpo a
- |amigae-request@bkhouse.cts.com| para escuchar todo sobre ello. Tambi\'en
- hay discusiones sobre~E en otras redes ({\it FidoNet}, {\it AmigaNet\/}), series de
- discos de dominio p\'ublico (EPD en Europa\b/Alemania, la misma direcci\'on
- que el lugar de registro alem\'an), adem\'as, hay gran cantidad de clubs de
- usuarios, BBS que apoyan~E\null{}. Simplemente echa un vistazo en tu zona.
- \pregunta{He oido hablar de esa lista de correo. ?`Qu\'e tal est\'a?}
- Compruebalo tu mismo. Si vas en serio con~E, es definitivamente
- imprescindible, adem\'as de que es el primer lugar en el que aparecen las
- noticias sobre~E.
- \pregunta{He tenido problemas para introducirme en la lista. ?`Podr\'{\i}as
- ocuparte tu de eso por mi?}
- Yo no tengo, personalmente, nada que ver con la administraci\'on de la
- lista, de forma que no te puedo ayudar m\'as que cualquier otro.
- Recuerda que el servidor es un proceso autom\'atizado, de forma que debes
- ser preciso en lo que le envias. No env\'{\i}es correo administrativo a la
- lista, en su lugar, intenta contactar con el administrador.
- \pregunta{Soy nuevo en Internet. ?`Me ayudar\'{\i}as a conseguir la lista de
- correo, ficheros FTP de {\it Aminet}, etc~\dots?}
- Cosas de este tipo van m\'as all\'a de mi cometido. Por favor, intenta
- contactar localmente con alguien.
- \pregunta{?`C\'omo se cual es la \'ultima versi\'on y c\'omo la recibo?}
- Si estas en la lista de correo ser\'as el primero en saberlo.
- {\it Aminet} es el primer lugar en el que aparecen las distribuciones y
- actualizaciones. Los usuarios registrados obtendr\'an las actualizaciones
- y/o notas de forma autom\'atica en su mbox.
- \pregunta{?`C\'omo registrarse?}
- Por favor mira en otra parte de este documento.
- \pregunta{?`Existe E para otras plataformas?}
- No todav\'{\i}a. Me he comprometido personalmente con un proyecto para
- realizar compiladores\b/traductores, y algunos otros tienen proyectos de
- compilador~E para otras plataformas, aunque de momento a\'un no hay nada.
- \pregunta{?`Puedo convertirme en un lugar de registro para el pa\'{\i}s~\/|X|?}
- Generalmente los lugares los elijo yo mismo cuando creo que es
- necesario y conozco muy bien a alguien en ese pa\'{\i}s.
- \pregunta{?`Puedo apoyar E con una BBS / con un club de programaci\'on~\dots?}
- Siempre puedes hacerlo, sin falta de preguntarme. Aunque por supuesto,
- me gusta tener noticias sobre esfuerzos de ese tipo~\dots
- \Espacio
- {\bf Programaci\'on}
- \pregunta{?`Puedo hacer \/|X| en E? (donde \/|X| = $\{$\/juegos, autoedici\'on,~\dots$\}$)}
- E es un lenguaje de programaci\'on de prop\'osito general, por lo que no
- deber\'{\i}a haber ning\'un tipo de programa que no se pueda hacer con~E (con
- alguna rara excepci\'on, que est\'a cubierta con el ensamblador en l\'{\i}nea
- de~E\null{}). Esto no significa que~E est\'e equipado especialmente para ciertos
- tipos de programas, es decir, E~no tiene funciones especiales para
- juegos (aunque su extensibilidad permite incorporarlas facilmente).
- \pregunta{?`C\'omo creo \/|X| en E? (donde \/|X| = $\{$\/ventana, manejador de
- interrupciones,~\dots$\}$)}
- Al igual que en la pregunta anterior, E~s\'olo abre la posibilidad de
- escribir lo que quieras, y no siempre tiene una funci\'on espec\'{\i}fica. En
- el peor de los casos eso significar\'a el usar funciones dif\'{\i}ciles de
- alguna librer\'{\i}a, aunque merece la pena meterte en detalle con eso. Si
- tienes suerte alg\'un otro programador ya habr\'a realizado algo parecido
- de lo que puedas aprender.
- \pregunta{Por favor escr\'{\i}beme un ejemplo de como hacer \/|X| en~E.}
- Por favor, intente imaginartelo t\'u mismo, o pregunta a otros programadores de~E.
- \pregunta{El compilador no quiere compilar cosas como \/|mipantalla.rastport.bitmap|,
- incluso cuando en general \/|x.y.z| es posible. ?`Por qu\'e?}
- Para poder hacer referencia al \'ultimo |bitmap|, el compilador necesita
- saber el tipo de la expresi\'on |mipantalla.rastport|. Y si miras en el
- m\'odulo |intuition/screens.m| ver\'as que el campo |rastport| no tiene tipo.
- \pregunta{\dots ?`por qu\'e no tenemos nuevos m\'odulos con tipos corregidos?}
- Porque los includes en ensamblador (|.o|) de los cuales se convierten los
- m\'odulos~E no contienen esa informaci\'on. No se pueden usar los ficheros
- |.h| de~C en su lugar, porque usan de alguna forma otros identificadores,
- y romper\'{\i}a la compatibiladad anterior.
- \pregunta{\dots entonces, ?`qu\'e hago?}
- El m\'etodo cl\'asico es poner |x.y| en un puntero con tipo, y entoces hacer
- referencia a |.z| desde \'ese. Con la mutaci\'on de punteros en~v3, tambi\'en
- puedes hacer referencia a \'el directamente (m\'{\i}ralo en otra parte de este
- documento).
- \pregunta{Cuando escribo c\'odigo como el siguiente el compilador me lo acepta,
- pero m\'as tarde me da problemas. ?`Qu\'e hay mal en este c\'odigo?}
- \qquad|DEF s[100]:STRING|\par
- \qquad|s:='mi bonita cadena'|
- \smallskip
- Si estas acostumbrado al {\sc BASIC}, por ejemplo, estar\'as acostumbrado a
- usar las cadenas de la misma forma que los enteros, ya que ambos son
- {\sl valores}. Sin embargo en~E no hay variables cadena reales en el
- sentido del {\sc BASIC}, el |DEF| anterior crea un trozo de memoria para
- almacenar la cadena, luego fija la variable como un puntero a esa
- memoria. El puntero y la memoria son, aparte de la implementaci\'on, dos
- entidades no relacionadas. A partir del |DEF|, todas las operaciones que
- acceden directamente a |s| est\'an accediendo al puntero. La asignaci\'on
- pone la direccion de |mi bonita cadena| en |s|, sobreescribiendo el
- valor anterior. La memoria de cadena creada por el |DEF| se mantiene
- inalterada, y ahora inaccesible ya que no hay ning\'un puntero que apunte
- ella. Las funciones como |StrCopy()| pueden usar ese puntero para
- encontrar la memoria real, y rellenarla:
- \qquad|StrCopy(s,'mi bonita cadena')|
- es correcto. Por supuesto, la asiganci\'on de cadenas como punteros
- tambi\'en es de utilidad, por ejemplo, si s\'olo quieres leer los datos de
- la cadenas, y no hacer nada m\'as con ellos, entonces:
- \qquad|DEF s:PTR TO CHAR|
- no reserva ninguna memoria para la cadena, s\'olo el puntero. La
- asignaci\'on anterior tendr\'{\i}a sentido ahora. Todo esto nos lleva a la
- diferencia entre punteros y valores (o sem\'antica por valor\b/referencia),
- y es importante que lo entiendas para programar en~E con \'exito.
- \pregunta{?`Como retorno un \/|STRING|, |OBJECT|, etc. de una funci\'on?}
- Depende. Si s\'olamente quieres utilizarlo como valor de retorno
- temporal, pasa una cadena como argumento y deja que la rutina la
- rellene. Si necesitas crear una cadena\b/objeto nuevo, reserv\'alo
- din\'amicamente dentro de la funci\'on, y retorna el puntero.
- \Espacio
- {\bf Errores}
- \pregunta{Recuerdo cuando estaba programando algo que de pronto el compilador
- rompi\'o\b/funcion\'o mal\b/produjo un error interno\b/gener\'o mensajes
- de error err\'oneos. ?`No deber\'{\i}as hacer algo sobre esto?}
- Si no tengo pistas sobre donde buscar un error, no podr\'e corregirlo. Si
- te encuentras con algo que estas seguro de que es un error del
- compilador, haz una copia del fuente que reproduce el error (si puedes
- recorta el fuente al m\'{\i}mino manteniendo el error) y env\'{\i}amelo con tanta
- informaci\'on como sea posible. Por ejemplo, los hits de |Enforcer| de~|EC|
- son bastante \'utiles.
- \pregunta{He escrito un programa \/|X|, pero rompe. Estoy seguro de que no tiene
- errores, por lo que debe ser un error del compilador.}
- Debido a la falta de tipos de E, nunca puedes estar completamente
- seguro de que tu c\'odigo es correcto. La mayor parte del c\'odigo que se
- me envi\'o con comentarios como el anterior se comprob\'o m\'as tarde que
- eran errores en el c\'odigo, casi siempre debidos a una falta de
- conocimiento de~E\null{}.\quad !`Lee la documentaci\'on, y usa |EDGB|!
- \Espacio
- {\bf Caracteristicas Futuras}
- ?`Tendr\'a E~\dots
- \pregunta{argumentos en registros?}
- Estoy seguro de que es posible, pero como muchas otras cosas, no es
- prioritario para m\'{\i}.
- \pregunta{enlazador de librer\'{\i}a/dispositvo (Library\b/Device)?}
- Ya lo habr\'{\i}a hecho si no fuera por la forma en que~E guarda la
- variables globales (en la pila), lo cual complica las cosas bastante.
- Esto simplemente necesitar\'a algo de tiempo.
- \pregunta{herencia m\'ultiple?}
- No es posible en E\null{}. La herencia m\'ultiple rompe la compatibilidad
- estructural entre objetos, y necesita de una comprobaci\'on de tipos
- bastante severa para resolverlo.
- \pregunta{|PROC|s dentro de |PROC|s?}
- No creo.
- \pregunta{arreglos multidimensionales?}
- Tampoco lo creo. Realmente en E no hay nada parecido a un arrreglo,
- s\'olo punteros que apuntan a grandes cantidades de objetos del mismo
- tama\~no. Para tener arreglos de dos dimensiones, ser\'{\i}a necesario tener
- el concepto de {\sl tama\~no\/} de un arreglo, lo cual~E no tiene.
- \pregunta{m\'as aopoyo a |020|/|881|?}
- Si, eventualmente. Aunque no est\'a entre las primeras cosas a realizar.
- \pregunta{sintaxis compatible con C?}
- A menudo la gente est\'a acostumbrada a alg\'un tipo de lenguaje
- (principalmente~C), y no entiende porque el dise\~no de un lenguaje de
- programaci\'on no es tan configurable como una utilidad de directorio o
- un editor de texto:\par
- {\obeylines
- \qquad {\sl Prefiero |==|/|=| m\'as que |=|/|:=|}
- \qquad {\sl ?`No puedes intercambiar |"| y |'| ?}
- \qquad {\sl ?`Por qu\'e |--| no funciona como en C?}
- \qquad {\sl !`Odio escribir las palabras clave en may\'usculas!}
- \qquad {\sl !`La falta de precedencia es odiosa!}}
- Las caracter\'{\i}sticas {\sl referidas} arriba jam\'as cambiar\'an, y ser\'a
- mejor que te acostumbres a ellas. Todas las decisiones de dise\~no tienen
- buenas razones, y al contrario de lo que dicen algunos rumores, no se
- hicieron por razones de velocidad del compilador (de hecho, el implementarlas
- de una forma tradicional no har\'{\i}a m\'as lento al compilador).
- \pregunta{?`Por qu\'e la caracteristica~\/|X| en~E no es como en el lenguaje~\/|Y|?
- (que yo encuentro mejor).}
- Lo mismo que antes, el dise\~no de un lenguaje no se puede cambiar debido
- a una preferencia personal. Si tienes ideas serias de c\'omo debe ser un
- lenguaje seg\'un tus preferencias, y esas ideas provienen del lenguaje |Y|,
- entonces utiliza |Y|\null{}. Si no encuentras tus ideas en ning\'un lenguaje
- existente, entonces !`es el momento de dise\~nar e implementar el tuyo
- propio! (No me estoy burlando, !`merece la pena!, y siempre puedes
- empezar con~E~\dots |:-)|)
- \pregunta{quiz\'as \/|X|?}
- Despu\'es de haber visto pr\'acticamente cientos de lenguajes de
- programaci\'on, las posibilidades que tienes de sugerir una nueva
- caracter\'{\i}stica para~E en la que no haya pensado, no son muy grandes.
- Muchas cosas no son apropiadas para~E, y en general el tiempo est\'a
- limitado para a\~nadir cosas m\'as interesante. (Si te fijas bien, la
- cantidad de caracter\'{\i}sticas de~E ya es bastante alta para un lenguaje
- de programaci\'on medio). Tengo una lista bastante grande de posibles
- caracter\'{\i}sticas para~E, y se implementar\'an eventualmente algunas de
- ellas. S\'olo espera y ver\'as~\dots
- \endchapter
- \eject
- ------------Corta por aqu
- -------------------
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Definitionen zur Unterst
- tzung des ECMA 94 Latin 1 Zeichensatzes.
- % Zusammengeleimt von Olaf `Olsen' Barthel, 7. April 1991
- % use or misuse this file as you like...
- % Probleme gibt es noch bei den Zeichen f
- r Yen, Cent und das
- % isl
- ndische Thorr. Hier m
- te man eigentlich mit Metafont
- % zuschlagen, wozu ich als TeX-Apprentice leider noch nicht
- % in der Lage bin :-(
- % little changes (hes) 9-jul-91
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % See the new `lplain.tex' for TeX 3.0 (>= Version 2.09 Feb 8, 1990)
- % if not(TeX >= 3.0) do_nothing else ...
- \ifx\undefined\inputlineno \else
- \ifnum\inputlineno=-1 \else
- \message{AMIGA-style (ECMA 94 Latin 1)}
- \lccode`
- \uccode`
- \lccode`
- \uccode`
- \catcode`
- =\active \def
- {\`{a}}
- \catcode`
- =\active \def
- {\`{A}}
- \lccode`
- \uccode`
- \lccode`
- \uccode`
- \catcode`
- =\active \def
- {\'{a}}
- \catcode`
- =\active \def
- {\'{A}}
- \lccode`
- \uccode`
- \lccode`
- \uccode`
- \catcode`
- =\active \def
- {\^{a}}
- \catcode`
- =\active \def
- {\^{A}}
- \lccode`
- \uccode`
- \lccode`
- \uccode`
- \catcode`
- =\active \def
- {\~{a}}
- \catcode`
- =\active \def
- {\~{A}}
- \lccode`
- \uccode`
- \lccode`
- \uccode`
- \catcode`
- =\active \def
- {\"{a}}
- \catcode`
- =\active \def
- {\"{A}}
- \lccode`
- \uccode`
- \lccode`
- \uccode`
- \catcode`
- =\active \def
- {\aa}
- \catcode`
- =\active \def
- {\AA}
- \lccode`
- \uccode`
- \lccode`
- \uccode`
- \catcode`
- =\active \def
- {\ae}
- \catcode`
- =\active \def
- {\AE}
- \lccode`
- \uccode`
- \lccode`
- \uccode`
- \catcode`
- =\active \def
- {\c{c}}
- \catcode`
- =\active \def
- {\c{C}}
- \lccode`
- \uccode`
- \lccode`
- \uccode`
- \catcode`
- =\active \def
- {\`{e}}
- \catcode`
- =\active \def
- {\`{E}}
- \lccode`
- \uccode`
- \lccode`
- \uccode`
- \catcode`
- =\active \def
- {\'{e}}
- \catcode`
- =\active \def
- {\'{E}}
- \lccode`
- \uccode`
- \lccode`
- \uccode`
- \catcode`
- =\active \def
- {\^{e}}
- \catcode`
- =\active \def
- {\^{E}}
- \lccode`
- \uccode`
- \lccode`
- \uccode`
- \catcode`
- =\active \def
- {\"{e}}
- \catcode`
- =\active \def
- {\"{E}}
- \lccode`
- \uccode`
- \lccode`
- \uccode`
- \catcode`
- =\active \def
- {\`{\i}}
- \catcode`
- =\active \def
- {\`{I}}
- \lccode`
- \uccode`
- \lccode`
- \uccode`
- \catcode`
- =\active \def
- {\'{\i}}
- \catcode`
- =\active \def
- {\'{I}}
- \lccode`
- \uccode`
- \lccode`
- \uccode`
- \catcode`
- =\active \def
- {\^{\i}}
- \catcode`
- =\active \def
- {\^{I}}
- \lccode`
- \uccode`
- \lccode`
- \uccode`
- \catcode`
- =\active \def
- {\"{\i}}
- \catcode`
- =\active \def
- {\"{I}}
- \lccode`
- \uccode`
- \lccode`
- \uccode`
- \catcode`
- =\active \def
- {\~{n}}
- \catcode`
- =\active \def
- {\~{N}}
- \lccode`
- \uccode`
- \lccode`
- \uccode`
- \catcode`
- =\active \def
- {\`{o}}
- \catcode`
- =\active \def
- {\`{O}}
- \lccode`
- \uccode`
- \lccode`
- \uccode`
- \catcode`
- =\active \def
- {\'{o}}
- \catcode`
- =\active \def
- {\'{O}}
- \lccode`
- \uccode`
- \lccode`
- \uccode`
- \catcode`
- =\active \def
- {\^{o}}
- \catcode`
- =\active \def
- {\^{O}}
- \lccode`
- \uccode`
- \lccode`
- \uccode`
- \catcode`
- =\active \def
- {\~{o}}
- \catcode`
- =\active \def
- {\~{O}}
- \lccode`
- \uccode`
- \lccode`
- \uccode`
- \catcode`
- =\active \def
- {\"{o}}
- \catcode`
- =\active \def
- {\"{O}}
- \lccode`
- \uccode`
- \lccode`
- \uccode`
- \catcode`
- =\active \def
- \catcode`
- =\active \def
- \lccode`
- \uccode`
- \catcode`
- =\active \def
- {$\times$}
- \lccode`
- \uccode`
- \catcode`
- =\active \def
- {$\div$}
- \lccode`
- \uccode`
- \lccode`
- \uccode`
- \catcode`
- =\active \def
- {\`{u}}
- \catcode`
- =\active \def
- {\`{U}}
- \lccode`
- \uccode`
- \lccode`
- \uccode`
- \catcode`
- =\active \def
- {\'{u}}
- \catcode`
- =\active \def
- {\'{U}}
- \lccode`
- \uccode`
- \lccode`
- \uccode`
- \catcode`
- =\active \def
- {\^{u}}
- \catcode`
- =\active \def
- {\^{U}}
- \lccode`
- \uccode`
- \lccode`
- \uccode`
- \catcode`
- =\active \def
- {\"{u}}
- \catcode`
- =\active \def
- {\"{U}}
- \lccode`
- \uccode`
- \lccode`
- \uccode`
- \catcode`
- =\active \def
- {\'{y}}
- \catcode`
- =\active \def
- {\'{Y}}
- \lccode`
- \uccode`
- \catcode`
- =\active \def
- {\ss}
- \lccode`
- \uccode`
- \catcode`
- =\active \def
- {\"{y}}
- \lccode`
- \uccode`
- \catcode`
- =\active \def
- \lccode`
- \uccode`
- \catcode`
- =\active \def
- {\pounds}
- \lccode`
- \uccode`
- \catcode`
- =\active \def
- \lccode`
- \uccode`
- \catcode`
- =\active \def
- {\copyright}
- \lccode`
- \uccode`
- \catcode`
- =\active \def
- {\leavevmode\kern-.1em\raise.5ex\hbox{\b{a}}}
- \lccode`
- \uccode`
- \catcode`
- =\active \def
- {$\ll$}
- \lccode`
- \uccode`
- \catcode`
- =\active \def
- {$\neg$}
- \lccode`
- \uccode`
- \catcode`
- =\active \def
- {$\pm$}
- \lccode`
- \uccode`
- \catcode`
- =\active \def
- {\leavevmode\kern.1em\raise.5ex\hbox{\the\scriptfont0 2}}
- \lccode`
- \uccode`
- \catcode`
- =\active \def
- {\leavevmode\kern.1em\raise.5ex\hbox{\the\scriptfont0 3}}
- \lccode`
- \uccode`
- \catcode`
- =\active \def
- {$\mu$}
- \lccode`
- \uccode`
- \catcode`
- =\active \def
- \lccode`
- \uccode`
- \catcode`
- =\active \def
- {\leavevmode\kern.1em\raise.5ex\hbox{\the\scriptfont0 1}}
- \lccode`
- \uccode`
- \catcode`
- =\active \def
- {\leavevmode\kern-.1em\raise.5ex\hbox{\b{o}}}
- \lccode`
- \uccode`
- \catcode`
- =\active \def
- {$\gg$}
- \lccode`
- \uccode`
- \catcode`
- =\active \def
- {\leavevmode\kern.1em\raise.5ex\hbox{\the\scriptfont0 1}\kern-.1em/\kern-.15em\lower.25ex\hbox{\the\scriptfont0 4}}
- \lccode`
- \uccode`
- \catcode`
- =\active \def
- {\leavevmode\kern.1em\raise.5ex\hbox{\the\scriptfont0 1}\kern-.1em/\kern-.15em\lower.25ex\hbox{\the\scriptfont0 2}}
- \lccode`
- \uccode`
- \catcode`
- =\active \def
- {\leavevmode\kern.1em\raise.5ex\hbox{\the\scriptfont0 3}\kern-.1em/\kern-.15em\lower.25ex\hbox{\the\scriptfont0 4}}
- \lccode`
- \uccode`
- \catcode`
- =\active \def
- % After transferring files there's sometimes an Ctrl-Z at the end.
- % (This could also handled in the CodePage with a line ^^Z>^^@)
- \catcode`^^Z=9 % ignore it or ...
- %\catcode`^^Z=\active \def^^Z{\endinput}% ... make it active
- \fi\fi
- \endinput
-